mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 20:39:57 +00:00
TUN-8052: Update go to 1.21.5
Also update golang.org/x/net and google.golang.org/grpc to fix vulnerabilities, although cloudflared is using them in a way that is not exposed to those risks
This commit is contained in:
357
vendor/google.golang.org/appengine/internal/api.go
generated
vendored
357
vendor/google.golang.org/appengine/internal/api.go
generated
vendored
@@ -2,12 +2,14 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -24,7 +26,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
|
||||
basepb "google.golang.org/appengine/internal/base"
|
||||
logpb "google.golang.org/appengine/internal/log"
|
||||
@@ -32,8 +33,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
apiPath = "/rpc_http"
|
||||
defaultTicketSuffix = "/default.20150612t184001.0"
|
||||
apiPath = "/rpc_http"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -65,21 +65,22 @@ var (
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
defaultTicketOnce sync.Once
|
||||
defaultTicket string
|
||||
backgroundContextOnce sync.Once
|
||||
backgroundContext netcontext.Context
|
||||
)
|
||||
|
||||
func apiURL() *url.URL {
|
||||
func apiURL(ctx context.Context) *url.URL {
|
||||
host, port := "appengine.googleapis.internal", "10001"
|
||||
if h := os.Getenv("API_HOST"); h != "" {
|
||||
host = h
|
||||
}
|
||||
if hostOverride := ctx.Value(apiHostOverrideKey); hostOverride != nil {
|
||||
host = hostOverride.(string)
|
||||
}
|
||||
if p := os.Getenv("API_PORT"); p != "" {
|
||||
port = p
|
||||
}
|
||||
if portOverride := ctx.Value(apiPortOverrideKey); portOverride != nil {
|
||||
port = portOverride.(string)
|
||||
}
|
||||
return &url.URL{
|
||||
Scheme: "http",
|
||||
Host: host + ":" + port,
|
||||
@@ -87,82 +88,97 @@ func apiURL() *url.URL {
|
||||
}
|
||||
}
|
||||
|
||||
func handleHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
c := &context{
|
||||
req: r,
|
||||
outHeader: w.Header(),
|
||||
apiURL: apiURL(),
|
||||
}
|
||||
r = r.WithContext(withContext(r.Context(), c))
|
||||
c.req = r
|
||||
|
||||
stopFlushing := make(chan int)
|
||||
|
||||
// Patch up RemoteAddr so it looks reasonable.
|
||||
if addr := r.Header.Get(userIPHeader); addr != "" {
|
||||
r.RemoteAddr = addr
|
||||
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
|
||||
r.RemoteAddr = addr
|
||||
} else {
|
||||
// Should not normally reach here, but pick a sensible default anyway.
|
||||
r.RemoteAddr = "127.0.0.1"
|
||||
}
|
||||
// The address in the headers will most likely be of these forms:
|
||||
// 123.123.123.123
|
||||
// 2001:db8::1
|
||||
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
|
||||
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
|
||||
// Assume the remote address is only a host; add a default port.
|
||||
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
|
||||
}
|
||||
|
||||
// Start goroutine responsible for flushing app logs.
|
||||
// This is done after adding c to ctx.m (and stopped before removing it)
|
||||
// because flushing logs requires making an API call.
|
||||
go c.logFlusher(stopFlushing)
|
||||
|
||||
executeRequestSafely(c, r)
|
||||
c.outHeader = nil // make sure header changes aren't respected any more
|
||||
|
||||
stopFlushing <- 1 // any logging beyond this point will be dropped
|
||||
|
||||
// Flush any pending logs asynchronously.
|
||||
c.pendingLogs.Lock()
|
||||
flushes := c.pendingLogs.flushes
|
||||
if len(c.pendingLogs.lines) > 0 {
|
||||
flushes++
|
||||
}
|
||||
c.pendingLogs.Unlock()
|
||||
flushed := make(chan struct{})
|
||||
go func() {
|
||||
defer close(flushed)
|
||||
// Force a log flush, because with very short requests we
|
||||
// may not ever flush logs.
|
||||
c.flushLog(true)
|
||||
}()
|
||||
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
|
||||
|
||||
// Avoid nil Write call if c.Write is never called.
|
||||
if c.outCode != 0 {
|
||||
w.WriteHeader(c.outCode)
|
||||
}
|
||||
if c.outBody != nil {
|
||||
w.Write(c.outBody)
|
||||
}
|
||||
// Wait for the last flush to complete before returning,
|
||||
// otherwise the security ticket will not be valid.
|
||||
<-flushed
|
||||
// Middleware wraps an http handler so that it can make GAE API calls
|
||||
func Middleware(next http.Handler) http.Handler {
|
||||
return handleHTTPMiddleware(executeRequestSafelyMiddleware(next))
|
||||
}
|
||||
|
||||
func executeRequestSafely(c *context, r *http.Request) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
|
||||
c.outCode = 500
|
||||
func handleHTTPMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
c := &aeContext{
|
||||
req: r,
|
||||
outHeader: w.Header(),
|
||||
}
|
||||
}()
|
||||
r = r.WithContext(withContext(r.Context(), c))
|
||||
c.req = r
|
||||
|
||||
http.DefaultServeMux.ServeHTTP(c, r)
|
||||
stopFlushing := make(chan int)
|
||||
|
||||
// Patch up RemoteAddr so it looks reasonable.
|
||||
if addr := r.Header.Get(userIPHeader); addr != "" {
|
||||
r.RemoteAddr = addr
|
||||
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
|
||||
r.RemoteAddr = addr
|
||||
} else {
|
||||
// Should not normally reach here, but pick a sensible default anyway.
|
||||
r.RemoteAddr = "127.0.0.1"
|
||||
}
|
||||
// The address in the headers will most likely be of these forms:
|
||||
// 123.123.123.123
|
||||
// 2001:db8::1
|
||||
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
|
||||
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
|
||||
// Assume the remote address is only a host; add a default port.
|
||||
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
|
||||
}
|
||||
|
||||
if logToLogservice() {
|
||||
// Start goroutine responsible for flushing app logs.
|
||||
// This is done after adding c to ctx.m (and stopped before removing it)
|
||||
// because flushing logs requires making an API call.
|
||||
go c.logFlusher(stopFlushing)
|
||||
}
|
||||
|
||||
next.ServeHTTP(c, r)
|
||||
c.outHeader = nil // make sure header changes aren't respected any more
|
||||
|
||||
flushed := make(chan struct{})
|
||||
if logToLogservice() {
|
||||
stopFlushing <- 1 // any logging beyond this point will be dropped
|
||||
|
||||
// Flush any pending logs asynchronously.
|
||||
c.pendingLogs.Lock()
|
||||
flushes := c.pendingLogs.flushes
|
||||
if len(c.pendingLogs.lines) > 0 {
|
||||
flushes++
|
||||
}
|
||||
c.pendingLogs.Unlock()
|
||||
go func() {
|
||||
defer close(flushed)
|
||||
// Force a log flush, because with very short requests we
|
||||
// may not ever flush logs.
|
||||
c.flushLog(true)
|
||||
}()
|
||||
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
|
||||
}
|
||||
|
||||
// Avoid nil Write call if c.Write is never called.
|
||||
if c.outCode != 0 {
|
||||
w.WriteHeader(c.outCode)
|
||||
}
|
||||
if c.outBody != nil {
|
||||
w.Write(c.outBody)
|
||||
}
|
||||
if logToLogservice() {
|
||||
// Wait for the last flush to complete before returning,
|
||||
// otherwise the security ticket will not be valid.
|
||||
<-flushed
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func executeRequestSafelyMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
c := w.(*aeContext)
|
||||
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
|
||||
c.outCode = 500
|
||||
}
|
||||
}()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func renderPanic(x interface{}) string {
|
||||
@@ -204,9 +220,9 @@ func renderPanic(x interface{}) string {
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// context represents the context of an in-flight HTTP request.
|
||||
// aeContext represents the aeContext of an in-flight HTTP request.
|
||||
// It implements the appengine.Context and http.ResponseWriter interfaces.
|
||||
type context struct {
|
||||
type aeContext struct {
|
||||
req *http.Request
|
||||
|
||||
outCode int
|
||||
@@ -218,8 +234,6 @@ type context struct {
|
||||
lines []*logpb.UserAppLogLine
|
||||
flushes int
|
||||
}
|
||||
|
||||
apiURL *url.URL
|
||||
}
|
||||
|
||||
var contextKey = "holds a *context"
|
||||
@@ -227,8 +241,8 @@ var contextKey = "holds a *context"
|
||||
// jointContext joins two contexts in a superficial way.
|
||||
// It takes values and timeouts from a base context, and only values from another context.
|
||||
type jointContext struct {
|
||||
base netcontext.Context
|
||||
valuesOnly netcontext.Context
|
||||
base context.Context
|
||||
valuesOnly context.Context
|
||||
}
|
||||
|
||||
func (c jointContext) Deadline() (time.Time, bool) {
|
||||
@@ -252,94 +266,54 @@ func (c jointContext) Value(key interface{}) interface{} {
|
||||
|
||||
// fromContext returns the App Engine context or nil if ctx is not
|
||||
// derived from an App Engine context.
|
||||
func fromContext(ctx netcontext.Context) *context {
|
||||
c, _ := ctx.Value(&contextKey).(*context)
|
||||
func fromContext(ctx context.Context) *aeContext {
|
||||
c, _ := ctx.Value(&contextKey).(*aeContext)
|
||||
return c
|
||||
}
|
||||
|
||||
func withContext(parent netcontext.Context, c *context) netcontext.Context {
|
||||
ctx := netcontext.WithValue(parent, &contextKey, c)
|
||||
func withContext(parent context.Context, c *aeContext) context.Context {
|
||||
ctx := context.WithValue(parent, &contextKey, c)
|
||||
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
|
||||
ctx = withNamespace(ctx, ns)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func toContext(c *context) netcontext.Context {
|
||||
return withContext(netcontext.Background(), c)
|
||||
func toContext(c *aeContext) context.Context {
|
||||
return withContext(context.Background(), c)
|
||||
}
|
||||
|
||||
func IncomingHeaders(ctx netcontext.Context) http.Header {
|
||||
func IncomingHeaders(ctx context.Context) http.Header {
|
||||
if c := fromContext(ctx); c != nil {
|
||||
return c.req.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReqContext(req *http.Request) netcontext.Context {
|
||||
func ReqContext(req *http.Request) context.Context {
|
||||
return req.Context()
|
||||
}
|
||||
|
||||
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
|
||||
func WithContext(parent context.Context, req *http.Request) context.Context {
|
||||
return jointContext{
|
||||
base: parent,
|
||||
valuesOnly: req.Context(),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultTicket returns a ticket used for background context or dev_appserver.
|
||||
func DefaultTicket() string {
|
||||
defaultTicketOnce.Do(func() {
|
||||
if IsDevAppServer() {
|
||||
defaultTicket = "testapp" + defaultTicketSuffix
|
||||
return
|
||||
}
|
||||
appID := partitionlessAppID()
|
||||
escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1)
|
||||
majVersion := VersionID(nil)
|
||||
if i := strings.Index(majVersion, "."); i > 0 {
|
||||
majVersion = majVersion[:i]
|
||||
}
|
||||
defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID())
|
||||
})
|
||||
return defaultTicket
|
||||
}
|
||||
|
||||
func BackgroundContext() netcontext.Context {
|
||||
backgroundContextOnce.Do(func() {
|
||||
// Compute background security ticket.
|
||||
ticket := DefaultTicket()
|
||||
|
||||
c := &context{
|
||||
req: &http.Request{
|
||||
Header: http.Header{
|
||||
ticketHeader: []string{ticket},
|
||||
},
|
||||
},
|
||||
apiURL: apiURL(),
|
||||
}
|
||||
backgroundContext = toContext(c)
|
||||
|
||||
// TODO(dsymonds): Wire up the shutdown handler to do a final flush.
|
||||
go c.logFlusher(make(chan int))
|
||||
})
|
||||
|
||||
return backgroundContext
|
||||
}
|
||||
|
||||
// RegisterTestRequest registers the HTTP request req for testing, such that
|
||||
// any API calls are sent to the provided URL. It returns a closure to delete
|
||||
// the registration.
|
||||
// any API calls are sent to the provided URL.
|
||||
// It should only be used by aetest package.
|
||||
func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) {
|
||||
c := &context{
|
||||
req: req,
|
||||
apiURL: apiURL,
|
||||
}
|
||||
ctx := withContext(decorate(req.Context()), c)
|
||||
req = req.WithContext(ctx)
|
||||
c.req = req
|
||||
return req, func() {}
|
||||
func RegisterTestRequest(req *http.Request, apiURL *url.URL, appID string) *http.Request {
|
||||
ctx := req.Context()
|
||||
ctx = withAPIHostOverride(ctx, apiURL.Hostname())
|
||||
ctx = withAPIPortOverride(ctx, apiURL.Port())
|
||||
ctx = WithAppIDOverride(ctx, appID)
|
||||
|
||||
// use the unregistered request as a placeholder so that withContext can read the headers
|
||||
c := &aeContext{req: req}
|
||||
c.req = req.WithContext(withContext(ctx, c))
|
||||
return c.req
|
||||
}
|
||||
|
||||
var errTimeout = &CallError{
|
||||
@@ -348,7 +322,7 @@ var errTimeout = &CallError{
|
||||
Timeout: true,
|
||||
}
|
||||
|
||||
func (c *context) Header() http.Header { return c.outHeader }
|
||||
func (c *aeContext) Header() http.Header { return c.outHeader }
|
||||
|
||||
// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
|
||||
// codes do not permit a response body (nor response entity headers such as
|
||||
@@ -365,7 +339,7 @@ func bodyAllowedForStatus(status int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *context) Write(b []byte) (int, error) {
|
||||
func (c *aeContext) Write(b []byte) (int, error) {
|
||||
if c.outCode == 0 {
|
||||
c.WriteHeader(http.StatusOK)
|
||||
}
|
||||
@@ -376,7 +350,7 @@ func (c *context) Write(b []byte) (int, error) {
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (c *context) WriteHeader(code int) {
|
||||
func (c *aeContext) WriteHeader(code int) {
|
||||
if c.outCode != 0 {
|
||||
logf(c, 3, "WriteHeader called multiple times on request.") // error level
|
||||
return
|
||||
@@ -384,10 +358,11 @@ func (c *context) WriteHeader(code int) {
|
||||
c.outCode = code
|
||||
}
|
||||
|
||||
func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) {
|
||||
func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, err error) {
|
||||
apiURL := apiURL(ctx)
|
||||
hreq := &http.Request{
|
||||
Method: "POST",
|
||||
URL: c.apiURL,
|
||||
URL: apiURL,
|
||||
Header: http.Header{
|
||||
apiEndpointHeader: apiEndpointHeaderValue,
|
||||
apiMethodHeader: apiMethodHeaderValue,
|
||||
@@ -396,13 +371,16 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error)
|
||||
},
|
||||
Body: ioutil.NopCloser(bytes.NewReader(body)),
|
||||
ContentLength: int64(len(body)),
|
||||
Host: c.apiURL.Host,
|
||||
Host: apiURL.Host,
|
||||
}
|
||||
if info := c.req.Header.Get(dapperHeader); info != "" {
|
||||
hreq.Header.Set(dapperHeader, info)
|
||||
}
|
||||
if info := c.req.Header.Get(traceHeader); info != "" {
|
||||
hreq.Header.Set(traceHeader, info)
|
||||
c := fromContext(ctx)
|
||||
if c != nil {
|
||||
if info := c.req.Header.Get(dapperHeader); info != "" {
|
||||
hreq.Header.Set(dapperHeader, info)
|
||||
}
|
||||
if info := c.req.Header.Get(traceHeader); info != "" {
|
||||
hreq.Header.Set(traceHeader, info)
|
||||
}
|
||||
}
|
||||
|
||||
tr := apiHTTPClient.Transport.(*http.Transport)
|
||||
@@ -444,7 +422,7 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error)
|
||||
return hrespBody, nil
|
||||
}
|
||||
|
||||
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
|
||||
func Call(ctx context.Context, service, method string, in, out proto.Message) error {
|
||||
if ns := NamespaceFromContext(ctx); ns != "" {
|
||||
if fn, ok := NamespaceMods[service]; ok {
|
||||
fn(in, ns)
|
||||
@@ -463,15 +441,11 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||
}
|
||||
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
// Give a good error message rather than a panic lower down.
|
||||
return errNotAppEngineContext
|
||||
}
|
||||
|
||||
// Apply transaction modifications if we're in a transaction.
|
||||
if t := transactionFromContext(ctx); t != nil {
|
||||
if t.finished {
|
||||
return errors.New("transaction context has expired")
|
||||
return errors.New("transaction aeContext has expired")
|
||||
}
|
||||
applyTransaction(in, &t.transaction)
|
||||
}
|
||||
@@ -487,20 +461,13 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||
return err
|
||||
}
|
||||
|
||||
ticket := c.req.Header.Get(ticketHeader)
|
||||
// Use a test ticket under test environment.
|
||||
if ticket == "" {
|
||||
if appid := ctx.Value(&appIDOverrideKey); appid != nil {
|
||||
ticket = appid.(string) + defaultTicketSuffix
|
||||
ticket := ""
|
||||
if c != nil {
|
||||
ticket = c.req.Header.Get(ticketHeader)
|
||||
if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" {
|
||||
ticket = dri
|
||||
}
|
||||
}
|
||||
// Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver.
|
||||
if ticket == "" {
|
||||
ticket = DefaultTicket()
|
||||
}
|
||||
if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" {
|
||||
ticket = dri
|
||||
}
|
||||
req := &remotepb.Request{
|
||||
ServiceName: &service,
|
||||
Method: &method,
|
||||
@@ -512,7 +479,7 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||
return err
|
||||
}
|
||||
|
||||
hrespBody, err := c.post(hreqBody, timeout)
|
||||
hrespBody, err := post(ctx, hreqBody, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -549,11 +516,11 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||
return proto.Unmarshal(res.Response, out)
|
||||
}
|
||||
|
||||
func (c *context) Request() *http.Request {
|
||||
func (c *aeContext) Request() *http.Request {
|
||||
return c.req
|
||||
}
|
||||
|
||||
func (c *context) addLogLine(ll *logpb.UserAppLogLine) {
|
||||
func (c *aeContext) addLogLine(ll *logpb.UserAppLogLine) {
|
||||
// Truncate long log lines.
|
||||
// TODO(dsymonds): Check if this is still necessary.
|
||||
const lim = 8 << 10
|
||||
@@ -575,18 +542,20 @@ var logLevelName = map[int64]string{
|
||||
4: "CRITICAL",
|
||||
}
|
||||
|
||||
func logf(c *context, level int64, format string, args ...interface{}) {
|
||||
func logf(c *aeContext, level int64, format string, args ...interface{}) {
|
||||
if c == nil {
|
||||
panic("not an App Engine context")
|
||||
panic("not an App Engine aeContext")
|
||||
}
|
||||
s := fmt.Sprintf(format, args...)
|
||||
s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
|
||||
c.addLogLine(&logpb.UserAppLogLine{
|
||||
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
|
||||
Level: &level,
|
||||
Message: &s,
|
||||
})
|
||||
// Only duplicate log to stderr if not running on App Engine second generation
|
||||
if logToLogservice() {
|
||||
c.addLogLine(&logpb.UserAppLogLine{
|
||||
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
|
||||
Level: &level,
|
||||
Message: &s,
|
||||
})
|
||||
}
|
||||
// Log to stdout if not deployed
|
||||
if !IsSecondGen() {
|
||||
log.Print(logLevelName[level] + ": " + s)
|
||||
}
|
||||
@@ -594,7 +563,7 @@ func logf(c *context, level int64, format string, args ...interface{}) {
|
||||
|
||||
// flushLog attempts to flush any pending logs to the appserver.
|
||||
// It should not be called concurrently.
|
||||
func (c *context) flushLog(force bool) (flushed bool) {
|
||||
func (c *aeContext) flushLog(force bool) (flushed bool) {
|
||||
c.pendingLogs.Lock()
|
||||
// Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
|
||||
n, rem := 0, 30<<20
|
||||
@@ -655,7 +624,7 @@ const (
|
||||
forceFlushInterval = 60 * time.Second
|
||||
)
|
||||
|
||||
func (c *context) logFlusher(stop <-chan int) {
|
||||
func (c *aeContext) logFlusher(stop <-chan int) {
|
||||
lastFlush := time.Now()
|
||||
tick := time.NewTicker(flushInterval)
|
||||
for {
|
||||
@@ -673,6 +642,12 @@ func (c *context) logFlusher(stop <-chan int) {
|
||||
}
|
||||
}
|
||||
|
||||
func ContextForTesting(req *http.Request) netcontext.Context {
|
||||
return toContext(&context{req: req})
|
||||
func ContextForTesting(req *http.Request) context.Context {
|
||||
return toContext(&aeContext{req: req})
|
||||
}
|
||||
|
||||
func logToLogservice() bool {
|
||||
// TODO: replace logservice with json structured logs to $LOG_DIR/app.log.json
|
||||
// where $LOG_DIR is /var/log in prod and some tmpdir in dev
|
||||
return os.Getenv("LOG_TO_LOGSERVICE") != "0"
|
||||
}
|
||||
|
29
vendor/google.golang.org/appengine/internal/api_classic.go
generated
vendored
29
vendor/google.golang.org/appengine/internal/api_classic.go
generated
vendored
@@ -2,11 +2,13 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -17,20 +19,19 @@ import (
|
||||
basepb "appengine_internal/base"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var contextKey = "holds an appengine.Context"
|
||||
|
||||
// fromContext returns the App Engine context or nil if ctx is not
|
||||
// derived from an App Engine context.
|
||||
func fromContext(ctx netcontext.Context) appengine.Context {
|
||||
func fromContext(ctx context.Context) appengine.Context {
|
||||
c, _ := ctx.Value(&contextKey).(appengine.Context)
|
||||
return c
|
||||
}
|
||||
|
||||
// This is only for classic App Engine adapters.
|
||||
func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
|
||||
func ClassicContextFromContext(ctx context.Context) (appengine.Context, error) {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
return nil, errNotAppEngineContext
|
||||
@@ -38,8 +39,8 @@ func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
|
||||
ctx := netcontext.WithValue(parent, &contextKey, c)
|
||||
func withContext(parent context.Context, c appengine.Context) context.Context {
|
||||
ctx := context.WithValue(parent, &contextKey, c)
|
||||
|
||||
s := &basepb.StringProto{}
|
||||
c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
|
||||
@@ -50,7 +51,7 @@ func withContext(parent netcontext.Context, c appengine.Context) netcontext.Cont
|
||||
return ctx
|
||||
}
|
||||
|
||||
func IncomingHeaders(ctx netcontext.Context) http.Header {
|
||||
func IncomingHeaders(ctx context.Context) http.Header {
|
||||
if c := fromContext(ctx); c != nil {
|
||||
if req, ok := c.Request().(*http.Request); ok {
|
||||
return req.Header
|
||||
@@ -59,11 +60,11 @@ func IncomingHeaders(ctx netcontext.Context) http.Header {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReqContext(req *http.Request) netcontext.Context {
|
||||
return WithContext(netcontext.Background(), req)
|
||||
func ReqContext(req *http.Request) context.Context {
|
||||
return WithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
|
||||
func WithContext(parent context.Context, req *http.Request) context.Context {
|
||||
c := appengine.NewContext(req)
|
||||
return withContext(parent, c)
|
||||
}
|
||||
@@ -83,11 +84,11 @@ func (t *testingContext) Call(service, method string, _, _ appengine_internal.Pr
|
||||
}
|
||||
func (t *testingContext) Request() interface{} { return t.req }
|
||||
|
||||
func ContextForTesting(req *http.Request) netcontext.Context {
|
||||
return withContext(netcontext.Background(), &testingContext{req: req})
|
||||
func ContextForTesting(req *http.Request) context.Context {
|
||||
return withContext(context.Background(), &testingContext{req: req})
|
||||
}
|
||||
|
||||
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
|
||||
func Call(ctx context.Context, service, method string, in, out proto.Message) error {
|
||||
if ns := NamespaceFromContext(ctx); ns != "" {
|
||||
if fn, ok := NamespaceMods[service]; ok {
|
||||
fn(in, ns)
|
||||
@@ -144,8 +145,8 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||
return err
|
||||
}
|
||||
|
||||
func handleHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
panic("handleHTTP called; this should be impossible")
|
||||
func Middleware(next http.Handler) http.Handler {
|
||||
panic("Middleware called; this should be impossible")
|
||||
}
|
||||
|
||||
func logf(c appengine.Context, level int64, format string, args ...interface{}) {
|
||||
|
50
vendor/google.golang.org/appengine/internal/api_common.go
generated
vendored
50
vendor/google.golang.org/appengine/internal/api_common.go
generated
vendored
@@ -5,20 +5,26 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type ctxKey string
|
||||
|
||||
func (c ctxKey) String() string {
|
||||
return "appengine context key: " + string(c)
|
||||
}
|
||||
|
||||
var errNotAppEngineContext = errors.New("not an App Engine context")
|
||||
|
||||
type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error
|
||||
type CallOverrideFunc func(ctx context.Context, service, method string, in, out proto.Message) error
|
||||
|
||||
var callOverrideKey = "holds []CallOverrideFunc"
|
||||
|
||||
func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Context {
|
||||
func WithCallOverride(ctx context.Context, f CallOverrideFunc) context.Context {
|
||||
// We avoid appending to any existing call override
|
||||
// so we don't risk overwriting a popped stack below.
|
||||
var cofs []CallOverrideFunc
|
||||
@@ -26,10 +32,10 @@ func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Con
|
||||
cofs = append(cofs, uf...)
|
||||
}
|
||||
cofs = append(cofs, f)
|
||||
return netcontext.WithValue(ctx, &callOverrideKey, cofs)
|
||||
return context.WithValue(ctx, &callOverrideKey, cofs)
|
||||
}
|
||||
|
||||
func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netcontext.Context, bool) {
|
||||
func callOverrideFromContext(ctx context.Context) (CallOverrideFunc, context.Context, bool) {
|
||||
cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc)
|
||||
if len(cofs) == 0 {
|
||||
return nil, nil, false
|
||||
@@ -37,7 +43,7 @@ func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netconte
|
||||
// We found a list of overrides; grab the last, and reconstitute a
|
||||
// context that will hide it.
|
||||
f := cofs[len(cofs)-1]
|
||||
ctx = netcontext.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
|
||||
ctx = context.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
|
||||
return f, ctx, true
|
||||
}
|
||||
|
||||
@@ -45,23 +51,35 @@ type logOverrideFunc func(level int64, format string, args ...interface{})
|
||||
|
||||
var logOverrideKey = "holds a logOverrideFunc"
|
||||
|
||||
func WithLogOverride(ctx netcontext.Context, f logOverrideFunc) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &logOverrideKey, f)
|
||||
func WithLogOverride(ctx context.Context, f logOverrideFunc) context.Context {
|
||||
return context.WithValue(ctx, &logOverrideKey, f)
|
||||
}
|
||||
|
||||
var appIDOverrideKey = "holds a string, being the full app ID"
|
||||
|
||||
func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &appIDOverrideKey, appID)
|
||||
func WithAppIDOverride(ctx context.Context, appID string) context.Context {
|
||||
return context.WithValue(ctx, &appIDOverrideKey, appID)
|
||||
}
|
||||
|
||||
var apiHostOverrideKey = ctxKey("holds a string, being the alternate API_HOST")
|
||||
|
||||
func withAPIHostOverride(ctx context.Context, apiHost string) context.Context {
|
||||
return context.WithValue(ctx, apiHostOverrideKey, apiHost)
|
||||
}
|
||||
|
||||
var apiPortOverrideKey = ctxKey("holds a string, being the alternate API_PORT")
|
||||
|
||||
func withAPIPortOverride(ctx context.Context, apiPort string) context.Context {
|
||||
return context.WithValue(ctx, apiPortOverrideKey, apiPort)
|
||||
}
|
||||
|
||||
var namespaceKey = "holds the namespace string"
|
||||
|
||||
func withNamespace(ctx netcontext.Context, ns string) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &namespaceKey, ns)
|
||||
func withNamespace(ctx context.Context, ns string) context.Context {
|
||||
return context.WithValue(ctx, &namespaceKey, ns)
|
||||
}
|
||||
|
||||
func NamespaceFromContext(ctx netcontext.Context) string {
|
||||
func NamespaceFromContext(ctx context.Context) string {
|
||||
// If there's no namespace, return the empty string.
|
||||
ns, _ := ctx.Value(&namespaceKey).(string)
|
||||
return ns
|
||||
@@ -70,14 +88,14 @@ func NamespaceFromContext(ctx netcontext.Context) string {
|
||||
// FullyQualifiedAppID returns the fully-qualified application ID.
|
||||
// This may contain a partition prefix (e.g. "s~" for High Replication apps),
|
||||
// or a domain prefix (e.g. "example.com:").
|
||||
func FullyQualifiedAppID(ctx netcontext.Context) string {
|
||||
func FullyQualifiedAppID(ctx context.Context) string {
|
||||
if id, ok := ctx.Value(&appIDOverrideKey).(string); ok {
|
||||
return id
|
||||
}
|
||||
return fullyQualifiedAppID(ctx)
|
||||
}
|
||||
|
||||
func Logf(ctx netcontext.Context, level int64, format string, args ...interface{}) {
|
||||
func Logf(ctx context.Context, level int64, format string, args ...interface{}) {
|
||||
if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok {
|
||||
f(level, format, args...)
|
||||
return
|
||||
@@ -90,7 +108,7 @@ func Logf(ctx netcontext.Context, level int64, format string, args ...interface{
|
||||
}
|
||||
|
||||
// NamespacedContext wraps a Context to support namespaces.
|
||||
func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context {
|
||||
func NamespacedContext(ctx context.Context, namespace string) context.Context {
|
||||
return withNamespace(ctx, namespace)
|
||||
}
|
||||
|
||||
|
7
vendor/google.golang.org/appengine/internal/identity.go
generated
vendored
7
vendor/google.golang.org/appengine/internal/identity.go
generated
vendored
@@ -5,9 +5,8 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,7 +22,7 @@ var (
|
||||
|
||||
// AppID is the implementation of the wrapper function of the same name in
|
||||
// ../identity.go. See that file for commentary.
|
||||
func AppID(c netcontext.Context) string {
|
||||
func AppID(c context.Context) string {
|
||||
return appID(FullyQualifiedAppID(c))
|
||||
}
|
||||
|
||||
@@ -35,7 +34,7 @@ func IsStandard() bool {
|
||||
return appengineStandard || IsSecondGen()
|
||||
}
|
||||
|
||||
// IsStandard is the implementation of the wrapper function of the same name in
|
||||
// IsSecondGen is the implementation of the wrapper function of the same name in
|
||||
// ../appengine.go. See that file for commentary.
|
||||
func IsSecondGen() bool {
|
||||
// Second-gen runtimes set $GAE_ENV so we use that to check if we're on a second-gen runtime.
|
||||
|
23
vendor/google.golang.org/appengine/internal/identity_classic.go
generated
vendored
23
vendor/google.golang.org/appengine/internal/identity_classic.go
generated
vendored
@@ -2,21 +2,22 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"appengine"
|
||||
"context"
|
||||
|
||||
netcontext "golang.org/x/net/context"
|
||||
"appengine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
appengineStandard = true
|
||||
}
|
||||
|
||||
func DefaultVersionHostname(ctx netcontext.Context) string {
|
||||
func DefaultVersionHostname(ctx context.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
@@ -24,12 +25,12 @@ func DefaultVersionHostname(ctx netcontext.Context) string {
|
||||
return appengine.DefaultVersionHostname(c)
|
||||
}
|
||||
|
||||
func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() }
|
||||
func ServerSoftware() string { return appengine.ServerSoftware() }
|
||||
func InstanceID() string { return appengine.InstanceID() }
|
||||
func IsDevAppServer() bool { return appengine.IsDevAppServer() }
|
||||
func Datacenter(_ context.Context) string { return appengine.Datacenter() }
|
||||
func ServerSoftware() string { return appengine.ServerSoftware() }
|
||||
func InstanceID() string { return appengine.InstanceID() }
|
||||
func IsDevAppServer() bool { return appengine.IsDevAppServer() }
|
||||
|
||||
func RequestID(ctx netcontext.Context) string {
|
||||
func RequestID(ctx context.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
@@ -37,14 +38,14 @@ func RequestID(ctx netcontext.Context) string {
|
||||
return appengine.RequestID(c)
|
||||
}
|
||||
|
||||
func ModuleName(ctx netcontext.Context) string {
|
||||
func ModuleName(ctx context.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
}
|
||||
return appengine.ModuleName(c)
|
||||
}
|
||||
func VersionID(ctx netcontext.Context) string {
|
||||
func VersionID(ctx context.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
@@ -52,7 +53,7 @@ func VersionID(ctx netcontext.Context) string {
|
||||
return appengine.VersionID(c)
|
||||
}
|
||||
|
||||
func fullyQualifiedAppID(ctx netcontext.Context) string {
|
||||
func fullyQualifiedAppID(ctx context.Context) string {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
panic(errNotAppEngineContext)
|
||||
|
1
vendor/google.golang.org/appengine/internal/identity_flex.go
generated
vendored
1
vendor/google.golang.org/appengine/internal/identity_flex.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build appenginevm
|
||||
// +build appenginevm
|
||||
|
||||
package internal
|
||||
|
20
vendor/google.golang.org/appengine/internal/identity_vm.go
generated
vendored
20
vendor/google.golang.org/appengine/internal/identity_vm.go
generated
vendored
@@ -2,17 +2,17 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
netcontext "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// These functions are implementations of the wrapper functions
|
||||
@@ -24,7 +24,7 @@ const (
|
||||
hDatacenter = "X-AppEngine-Datacenter"
|
||||
)
|
||||
|
||||
func ctxHeaders(ctx netcontext.Context) http.Header {
|
||||
func ctxHeaders(ctx context.Context) http.Header {
|
||||
c := fromContext(ctx)
|
||||
if c == nil {
|
||||
return nil
|
||||
@@ -32,15 +32,15 @@ func ctxHeaders(ctx netcontext.Context) http.Header {
|
||||
return c.Request().Header
|
||||
}
|
||||
|
||||
func DefaultVersionHostname(ctx netcontext.Context) string {
|
||||
func DefaultVersionHostname(ctx context.Context) string {
|
||||
return ctxHeaders(ctx).Get(hDefaultVersionHostname)
|
||||
}
|
||||
|
||||
func RequestID(ctx netcontext.Context) string {
|
||||
func RequestID(ctx context.Context) string {
|
||||
return ctxHeaders(ctx).Get(hRequestLogId)
|
||||
}
|
||||
|
||||
func Datacenter(ctx netcontext.Context) string {
|
||||
func Datacenter(ctx context.Context) string {
|
||||
if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" {
|
||||
return dc
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func ServerSoftware() string {
|
||||
|
||||
// TODO(dsymonds): Remove the metadata fetches.
|
||||
|
||||
func ModuleName(_ netcontext.Context) string {
|
||||
func ModuleName(_ context.Context) string {
|
||||
if s := os.Getenv("GAE_MODULE_NAME"); s != "" {
|
||||
return s
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func ModuleName(_ netcontext.Context) string {
|
||||
return string(mustGetMetadata("instance/attributes/gae_backend_name"))
|
||||
}
|
||||
|
||||
func VersionID(_ netcontext.Context) string {
|
||||
func VersionID(_ context.Context) string {
|
||||
if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" {
|
||||
return s1 + "." + s2
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func partitionlessAppID() string {
|
||||
return string(mustGetMetadata("instance/attributes/gae_project"))
|
||||
}
|
||||
|
||||
func fullyQualifiedAppID(_ netcontext.Context) string {
|
||||
func fullyQualifiedAppID(_ context.Context) string {
|
||||
if s := os.Getenv("GAE_APPLICATION"); s != "" {
|
||||
return s
|
||||
}
|
||||
@@ -130,5 +130,5 @@ func fullyQualifiedAppID(_ netcontext.Context) string {
|
||||
}
|
||||
|
||||
func IsDevAppServer() bool {
|
||||
return os.Getenv("RUN_WITH_DEVAPPSERVER") != ""
|
||||
return os.Getenv("RUN_WITH_DEVAPPSERVER") != "" || os.Getenv("GAE_ENV") == "localdev"
|
||||
}
|
||||
|
1
vendor/google.golang.org/appengine/internal/main.go
generated
vendored
1
vendor/google.golang.org/appengine/internal/main.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
package internal
|
||||
|
3
vendor/google.golang.org/appengine/internal/main_vm.go
generated
vendored
3
vendor/google.golang.org/appengine/internal/main_vm.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
package internal
|
||||
@@ -29,7 +30,7 @@ func Main() {
|
||||
if IsDevAppServer() {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil {
|
||||
if err := http.ListenAndServe(host+":"+port, Middleware(http.DefaultServeMux)); err != nil {
|
||||
log.Fatalf("http.ListenAndServe: %v", err)
|
||||
}
|
||||
}
|
||||
|
10
vendor/google.golang.org/appengine/internal/transaction.go
generated
vendored
10
vendor/google.golang.org/appengine/internal/transaction.go
generated
vendored
@@ -7,11 +7,11 @@ package internal
|
||||
// This file implements hooks for applying datastore transactions.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
netcontext "golang.org/x/net/context"
|
||||
|
||||
basepb "google.golang.org/appengine/internal/base"
|
||||
pb "google.golang.org/appengine/internal/datastore"
|
||||
@@ -38,13 +38,13 @@ func applyTransaction(pb proto.Message, t *pb.Transaction) {
|
||||
|
||||
var transactionKey = "used for *Transaction"
|
||||
|
||||
func transactionFromContext(ctx netcontext.Context) *transaction {
|
||||
func transactionFromContext(ctx context.Context) *transaction {
|
||||
t, _ := ctx.Value(&transactionKey).(*transaction)
|
||||
return t
|
||||
}
|
||||
|
||||
func withTransaction(ctx netcontext.Context, t *transaction) netcontext.Context {
|
||||
return netcontext.WithValue(ctx, &transactionKey, t)
|
||||
func withTransaction(ctx context.Context, t *transaction) context.Context {
|
||||
return context.WithValue(ctx, &transactionKey, t)
|
||||
}
|
||||
|
||||
type transaction struct {
|
||||
@@ -54,7 +54,7 @@ type transaction struct {
|
||||
|
||||
var ErrConcurrentTransaction = errors.New("internal: concurrent transaction")
|
||||
|
||||
func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
|
||||
func RunTransactionOnce(c context.Context, f func(context.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
|
||||
if transactionFromContext(c) != nil {
|
||||
return nil, errors.New("nested transactions are not supported")
|
||||
}
|
||||
|
9
vendor/google.golang.org/appengine/urlfetch/urlfetch.go
generated
vendored
9
vendor/google.golang.org/appengine/urlfetch/urlfetch.go
generated
vendored
@@ -7,6 +7,7 @@
|
||||
package urlfetch // import "google.golang.org/appengine/urlfetch"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -18,7 +19,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"google.golang.org/appengine/internal"
|
||||
pb "google.golang.org/appengine/internal/urlfetch"
|
||||
@@ -44,11 +44,10 @@ type Transport struct {
|
||||
var _ http.RoundTripper = (*Transport)(nil)
|
||||
|
||||
// Client returns an *http.Client using a default urlfetch Transport. This
|
||||
// client will have the default deadline of 5 seconds, and will check the
|
||||
// validity of SSL certificates.
|
||||
// client will check the validity of SSL certificates.
|
||||
//
|
||||
// Any deadline of the provided context will be used for requests through this client;
|
||||
// if the client does not have a deadline then a 5 second default is used.
|
||||
// Any deadline of the provided context will be used for requests through this client.
|
||||
// If the client does not have a deadline, then an App Engine default of 60 second is used.
|
||||
func Client(ctx context.Context) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &Transport{
|
||||
|
4
vendor/google.golang.org/genproto/googleapis/api/httpbody/httpbody.pb.go
generated
vendored
4
vendor/google.golang.org/genproto/googleapis/api/httpbody/httpbody.pb.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 Google LLC
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.2
|
||||
// protoc v3.21.9
|
||||
// source: google/api/httpbody.proto
|
||||
|
||||
package httpbody
|
||||
|
202
vendor/google.golang.org/genproto/googleapis/rpc/LICENSE
generated
vendored
Normal file
202
vendor/google.golang.org/genproto/googleapis/rpc/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
10
vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
generated
vendored
10
vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.2
|
||||
// protoc v3.21.9
|
||||
// source: google/rpc/status.proto
|
||||
|
||||
package status
|
||||
@@ -48,11 +48,13 @@ type Status struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
|
||||
// The status code, which should be an enum value of
|
||||
// [google.rpc.Code][google.rpc.Code].
|
||||
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||
// A developer-facing error message, which should be in English. Any
|
||||
// user-facing error message should be localized and sent in the
|
||||
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
|
||||
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized
|
||||
// by the client.
|
||||
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
|
||||
// A list of messages that carry the error details. There is a common set of
|
||||
// message types for APIs to use.
|
||||
|
23
vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go
generated
vendored
23
vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package field_mask aliases all exported identifiers in
|
||||
// package "google.golang.org/protobuf/types/known/fieldmaskpb".
|
||||
package field_mask
|
||||
|
||||
import "google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
|
||||
type FieldMask = fieldmaskpb.FieldMask
|
||||
|
||||
var File_google_protobuf_field_mask_proto = fieldmaskpb.File_google_protobuf_field_mask_proto
|
25
vendor/google.golang.org/grpc/CONTRIBUTING.md
generated
vendored
25
vendor/google.golang.org/grpc/CONTRIBUTING.md
generated
vendored
@@ -20,6 +20,15 @@ How to get your contributions merged smoothly and quickly.
|
||||
both author's & review's time is wasted. Create more PRs to address different
|
||||
concerns and everyone will be happy.
|
||||
|
||||
- If you are searching for features to work on, issues labeled [Status: Help
|
||||
Wanted](https://github.com/grpc/grpc-go/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Status%3A+Help+Wanted%22)
|
||||
is a great place to start. These issues are well-documented and usually can be
|
||||
resolved with a single pull request.
|
||||
|
||||
- If you are adding a new file, make sure it has the copyright message template
|
||||
at the top as a comment. You can copy over the message from an existing file
|
||||
and update the year.
|
||||
|
||||
- The grpc package should only depend on standard Go packages and a small number
|
||||
of exceptions. If your contribution introduces new dependencies which are NOT
|
||||
in the [list](https://godoc.org/google.golang.org/grpc?imports), you need a
|
||||
@@ -32,14 +41,18 @@ How to get your contributions merged smoothly and quickly.
|
||||
- Provide a good **PR description** as a record of **what** change is being made
|
||||
and **why** it was made. Link to a github issue if it exists.
|
||||
|
||||
- Don't fix code style and formatting unless you are already changing that line
|
||||
to address an issue. PRs with irrelevant changes won't be merged. If you do
|
||||
want to fix formatting or style, do that in a separate PR.
|
||||
- If you want to fix formatting or style, consider whether your changes are an
|
||||
obvious improvement or might be considered a personal preference. If a style
|
||||
change is based on preference, it likely will not be accepted. If it corrects
|
||||
widely agreed-upon anti-patterns, then please do create a PR and explain the
|
||||
benefits of the change.
|
||||
|
||||
- Unless your PR is trivial, you should expect there will be reviewer comments
|
||||
that you'll need to address before merging. We expect you to be reasonably
|
||||
responsive to those comments, otherwise the PR will be closed after 2-3 weeks
|
||||
of inactivity.
|
||||
that you'll need to address before merging. We'll mark it as `Status: Requires
|
||||
Reporter Clarification` if we expect you to respond to these comments in a
|
||||
timely manner. If the PR remains inactive for 6 days, it will be marked as
|
||||
`stale` and automatically close 7 days after that if we don't hear back from
|
||||
you.
|
||||
|
||||
- Maintain **clean commit history** and use **meaningful commit messages**. PRs
|
||||
with messy commit history are difficult to review and won't be merged. Use
|
||||
|
60
vendor/google.golang.org/grpc/README.md
generated
vendored
60
vendor/google.golang.org/grpc/README.md
generated
vendored
@@ -1,8 +1,8 @@
|
||||
# gRPC-Go
|
||||
|
||||
[](https://travis-ci.org/grpc/grpc-go)
|
||||
[][API]
|
||||
[](https://goreportcard.com/report/github.com/grpc/grpc-go)
|
||||
[](https://codecov.io/gh/grpc/grpc-go)
|
||||
|
||||
The [Go][] implementation of [gRPC][]: A high performance, open source, general
|
||||
RPC framework that puts mobile and HTTP/2 first. For more information see the
|
||||
@@ -14,21 +14,14 @@ RPC framework that puts mobile and HTTP/2 first. For more information see the
|
||||
|
||||
## Installation
|
||||
|
||||
With [Go module][] support (Go 1.11+), simply add the following import
|
||||
Simply add the following import to your code, and then `go [build|run|test]`
|
||||
will automatically fetch the necessary dependencies:
|
||||
|
||||
|
||||
```go
|
||||
import "google.golang.org/grpc"
|
||||
```
|
||||
|
||||
to your code, and then `go [build|run|test]` will automatically fetch the
|
||||
necessary dependencies.
|
||||
|
||||
Otherwise, to install the `grpc-go` package, run the following command:
|
||||
|
||||
```console
|
||||
$ go get -u google.golang.org/grpc
|
||||
```
|
||||
|
||||
> **Note:** If you are trying to access `grpc-go` from **China**, see the
|
||||
> [FAQ](#FAQ) below.
|
||||
|
||||
@@ -56,15 +49,6 @@ To build Go code, there are several options:
|
||||
|
||||
- Set up a VPN and access google.golang.org through that.
|
||||
|
||||
- Without Go module support: `git clone` the repo manually:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
|
||||
```
|
||||
|
||||
You will need to do the same for all of grpc's dependencies in `golang.org`,
|
||||
e.g. `golang.org/x/net`.
|
||||
|
||||
- With Go module support: it is possible to use the `replace` feature of `go
|
||||
mod` to create aliases for golang.org packages. In your project's directory:
|
||||
|
||||
@@ -76,33 +60,13 @@ To build Go code, there are several options:
|
||||
```
|
||||
|
||||
Again, this will need to be done for all transitive dependencies hosted on
|
||||
golang.org as well. For details, refer to [golang/go issue #28652](https://github.com/golang/go/issues/28652).
|
||||
golang.org as well. For details, refer to [golang/go issue
|
||||
#28652](https://github.com/golang/go/issues/28652).
|
||||
|
||||
### Compiling error, undefined: grpc.SupportPackageIsVersion
|
||||
|
||||
#### If you are using Go modules:
|
||||
|
||||
Ensure your gRPC-Go version is `require`d at the appropriate version in
|
||||
the same module containing the generated `.pb.go` files. For example,
|
||||
`SupportPackageIsVersion6` needs `v1.27.0`, so in your `go.mod` file:
|
||||
|
||||
```go
|
||||
module <your module name>
|
||||
|
||||
require (
|
||||
google.golang.org/grpc v1.27.0
|
||||
)
|
||||
```
|
||||
|
||||
#### If you are *not* using Go modules:
|
||||
|
||||
Update the `proto` package, gRPC package, and rebuild the `.proto` files:
|
||||
|
||||
```sh
|
||||
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
|
||||
go get -u google.golang.org/grpc
|
||||
protoc --go_out=plugins=grpc:. *.proto
|
||||
```
|
||||
Please update to the latest version of gRPC-Go using
|
||||
`go get google.golang.org/grpc`.
|
||||
|
||||
### How to turn on logging
|
||||
|
||||
@@ -121,9 +85,11 @@ possible reasons, including:
|
||||
1. mis-configured transport credentials, connection failed on handshaking
|
||||
1. bytes disrupted, possibly by a proxy in between
|
||||
1. server shutdown
|
||||
1. Keepalive parameters caused connection shutdown, for example if you have configured
|
||||
your server to terminate connections regularly to [trigger DNS lookups](https://github.com/grpc/grpc-go/issues/3170#issuecomment-552517779).
|
||||
If this is the case, you may want to increase your [MaxConnectionAgeGrace](https://pkg.go.dev/google.golang.org/grpc/keepalive?tab=doc#ServerParameters),
|
||||
1. Keepalive parameters caused connection shutdown, for example if you have
|
||||
configured your server to terminate connections regularly to [trigger DNS
|
||||
lookups](https://github.com/grpc/grpc-go/issues/3170#issuecomment-552517779).
|
||||
If this is the case, you may want to increase your
|
||||
[MaxConnectionAgeGrace](https://pkg.go.dev/google.golang.org/grpc/keepalive?tab=doc#ServerParameters),
|
||||
to allow longer RPC calls to finish.
|
||||
|
||||
It can be tricky to debug this because the error happens on the client side but
|
||||
|
72
vendor/google.golang.org/grpc/attributes/attributes.go
generated
vendored
72
vendor/google.golang.org/grpc/attributes/attributes.go
generated
vendored
@@ -25,30 +25,35 @@
|
||||
// later release.
|
||||
package attributes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Attributes is an immutable struct for storing and retrieving generic
|
||||
// key/value pairs. Keys must be hashable, and users should define their own
|
||||
// types for keys. Values should not be modified after they are added to an
|
||||
// Attributes or if they were received from one. If values implement 'Equal(o
|
||||
// interface{}) bool', it will be called by (*Attributes).Equal to determine
|
||||
// whether two values with the same key should be considered equal.
|
||||
// any) bool', it will be called by (*Attributes).Equal to determine whether
|
||||
// two values with the same key should be considered equal.
|
||||
type Attributes struct {
|
||||
m map[interface{}]interface{}
|
||||
m map[any]any
|
||||
}
|
||||
|
||||
// New returns a new Attributes containing the key/value pair.
|
||||
func New(key, value interface{}) *Attributes {
|
||||
return &Attributes{m: map[interface{}]interface{}{key: value}}
|
||||
func New(key, value any) *Attributes {
|
||||
return &Attributes{m: map[any]any{key: value}}
|
||||
}
|
||||
|
||||
// WithValue returns a new Attributes containing the previous keys and values
|
||||
// and the new key/value pair. If the same key appears multiple times, the
|
||||
// last value overwrites all previous values for that key. To remove an
|
||||
// existing key, use a nil value. value should not be modified later.
|
||||
func (a *Attributes) WithValue(key, value interface{}) *Attributes {
|
||||
func (a *Attributes) WithValue(key, value any) *Attributes {
|
||||
if a == nil {
|
||||
return New(key, value)
|
||||
}
|
||||
n := &Attributes{m: make(map[interface{}]interface{}, len(a.m)+1)}
|
||||
n := &Attributes{m: make(map[any]any, len(a.m)+1)}
|
||||
for k, v := range a.m {
|
||||
n.m[k] = v
|
||||
}
|
||||
@@ -58,20 +63,19 @@ func (a *Attributes) WithValue(key, value interface{}) *Attributes {
|
||||
|
||||
// Value returns the value associated with these attributes for key, or nil if
|
||||
// no value is associated with key. The returned value should not be modified.
|
||||
func (a *Attributes) Value(key interface{}) interface{} {
|
||||
func (a *Attributes) Value(key any) any {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
return a.m[key]
|
||||
}
|
||||
|
||||
// Equal returns whether a and o are equivalent. If 'Equal(o interface{})
|
||||
// bool' is implemented for a value in the attributes, it is called to
|
||||
// determine if the value matches the one stored in the other attributes. If
|
||||
// Equal is not implemented, standard equality is used to determine if the two
|
||||
// values are equal. Note that some types (e.g. maps) aren't comparable by
|
||||
// default, so they must be wrapped in a struct, or in an alias type, with Equal
|
||||
// defined.
|
||||
// Equal returns whether a and o are equivalent. If 'Equal(o any) bool' is
|
||||
// implemented for a value in the attributes, it is called to determine if the
|
||||
// value matches the one stored in the other attributes. If Equal is not
|
||||
// implemented, standard equality is used to determine if the two values are
|
||||
// equal. Note that some types (e.g. maps) aren't comparable by default, so
|
||||
// they must be wrapped in a struct, or in an alias type, with Equal defined.
|
||||
func (a *Attributes) Equal(o *Attributes) bool {
|
||||
if a == nil && o == nil {
|
||||
return true
|
||||
@@ -88,7 +92,7 @@ func (a *Attributes) Equal(o *Attributes) bool {
|
||||
// o missing element of a
|
||||
return false
|
||||
}
|
||||
if eq, ok := v.(interface{ Equal(o interface{}) bool }); ok {
|
||||
if eq, ok := v.(interface{ Equal(o any) bool }); ok {
|
||||
if !eq.Equal(ov) {
|
||||
return false
|
||||
}
|
||||
@@ -99,3 +103,39 @@ func (a *Attributes) Equal(o *Attributes) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// String prints the attribute map. If any key or values throughout the map
|
||||
// implement fmt.Stringer, it calls that method and appends.
|
||||
func (a *Attributes) String() string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("{")
|
||||
first := true
|
||||
for k, v := range a.m {
|
||||
if !first {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%q: %q ", str(k), str(v)))
|
||||
first = false
|
||||
}
|
||||
sb.WriteString("}")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func str(x any) (s string) {
|
||||
if v, ok := x.(fmt.Stringer); ok {
|
||||
return fmt.Sprint(v)
|
||||
} else if v, ok := x.(string); ok {
|
||||
return v
|
||||
}
|
||||
return fmt.Sprintf("<%p>", x)
|
||||
}
|
||||
|
||||
// MarshalJSON helps implement the json.Marshaler interface, thereby rendering
|
||||
// the Attributes correctly when printing (via pretty.JSON) structs containing
|
||||
// Attributes as fields.
|
||||
//
|
||||
// Is it impossible to unmarshal attributes from a JSON representation and this
|
||||
// method is meant only for debugging purposes.
|
||||
func (a *Attributes) MarshalJSON() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
}
|
||||
|
70
vendor/google.golang.org/grpc/balancer/balancer.go
generated
vendored
70
vendor/google.golang.org/grpc/balancer/balancer.go
generated
vendored
@@ -30,6 +30,7 @@ import (
|
||||
"google.golang.org/grpc/channelz"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/resolver"
|
||||
@@ -39,6 +40,8 @@ import (
|
||||
var (
|
||||
// m is a map from name to balancer builder.
|
||||
m = make(map[string]Builder)
|
||||
|
||||
logger = grpclog.Component("balancer")
|
||||
)
|
||||
|
||||
// Register registers the balancer builder to the balancer map. b.Name
|
||||
@@ -51,6 +54,12 @@ var (
|
||||
// an init() function), and is not thread-safe. If multiple Balancers are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func Register(b Builder) {
|
||||
if strings.ToLower(b.Name()) != b.Name() {
|
||||
// TODO: Skip the use of strings.ToLower() to index the map after v1.59
|
||||
// is released to switch to case sensitive balancer registry. Also,
|
||||
// remove this warning and update the docstrings for Register and Get.
|
||||
logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon", b.Name())
|
||||
}
|
||||
m[strings.ToLower(b.Name())] = b
|
||||
}
|
||||
|
||||
@@ -70,6 +79,12 @@ func init() {
|
||||
// Note that the compare is done in a case-insensitive fashion.
|
||||
// If no builder is register with the name, nil will be returned.
|
||||
func Get(name string) Builder {
|
||||
if strings.ToLower(name) != name {
|
||||
// TODO: Skip the use of strings.ToLower() to index the map after v1.59
|
||||
// is released to switch to case sensitive balancer registry. Also,
|
||||
// remove this warning and update the docstrings for Register and Get.
|
||||
logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon", name)
|
||||
}
|
||||
if b, ok := m[strings.ToLower(name)]; ok {
|
||||
return b
|
||||
}
|
||||
@@ -105,8 +120,8 @@ type SubConn interface {
|
||||
//
|
||||
// This will trigger a state transition for the SubConn.
|
||||
//
|
||||
// Deprecated: This method is now part of the ClientConn interface and will
|
||||
// eventually be removed from here.
|
||||
// Deprecated: this method will be removed. Create new SubConns for new
|
||||
// addresses instead.
|
||||
UpdateAddresses([]resolver.Address)
|
||||
// Connect starts the connecting for this SubConn.
|
||||
Connect()
|
||||
@@ -115,6 +130,13 @@ type SubConn interface {
|
||||
// creates a new one and returns it. Returns a close function which must
|
||||
// be called when the Producer is no longer needed.
|
||||
GetOrBuildProducer(ProducerBuilder) (p Producer, close func())
|
||||
// Shutdown shuts down the SubConn gracefully. Any started RPCs will be
|
||||
// allowed to complete. No future calls should be made on the SubConn.
|
||||
// One final state update will be delivered to the StateListener (or
|
||||
// UpdateSubConnState; deprecated) with ConnectivityState of Shutdown to
|
||||
// indicate the shutdown operation. This may be delivered before
|
||||
// in-progress RPCs are complete and the actual connection is closed.
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
// NewSubConnOptions contains options to create new SubConn.
|
||||
@@ -129,6 +151,11 @@ type NewSubConnOptions struct {
|
||||
// HealthCheckEnabled indicates whether health check service should be
|
||||
// enabled on this SubConn
|
||||
HealthCheckEnabled bool
|
||||
// StateListener is called when the state of the subconn changes. If nil,
|
||||
// Balancer.UpdateSubConnState will be called instead. Will never be
|
||||
// invoked until after Connect() is called on the SubConn created with
|
||||
// these options.
|
||||
StateListener func(SubConnState)
|
||||
}
|
||||
|
||||
// State contains the balancer's state relevant to the gRPC ClientConn.
|
||||
@@ -150,16 +177,24 @@ type ClientConn interface {
|
||||
// NewSubConn is called by balancer to create a new SubConn.
|
||||
// It doesn't block and wait for the connections to be established.
|
||||
// Behaviors of the SubConn can be controlled by options.
|
||||
//
|
||||
// Deprecated: please be aware that in a future version, SubConns will only
|
||||
// support one address per SubConn.
|
||||
NewSubConn([]resolver.Address, NewSubConnOptions) (SubConn, error)
|
||||
// RemoveSubConn removes the SubConn from ClientConn.
|
||||
// The SubConn will be shutdown.
|
||||
//
|
||||
// Deprecated: use SubConn.Shutdown instead.
|
||||
RemoveSubConn(SubConn)
|
||||
// UpdateAddresses updates the addresses used in the passed in SubConn.
|
||||
// gRPC checks if the currently connected address is still in the new list.
|
||||
// If so, the connection will be kept. Else, the connection will be
|
||||
// gracefully closed, and a new connection will be created.
|
||||
//
|
||||
// This will trigger a state transition for the SubConn.
|
||||
// This may trigger a state transition for the SubConn.
|
||||
//
|
||||
// Deprecated: this method will be removed. Create new SubConns for new
|
||||
// addresses instead.
|
||||
UpdateAddresses(SubConn, []resolver.Address)
|
||||
|
||||
// UpdateState notifies gRPC that the balancer's internal state has
|
||||
@@ -250,7 +285,7 @@ type DoneInfo struct {
|
||||
// trailing metadata.
|
||||
//
|
||||
// The only supported type now is *orca_v3.LoadReport.
|
||||
ServerLoad interface{}
|
||||
ServerLoad any
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -279,6 +314,14 @@ type PickResult struct {
|
||||
// type, Done may not be called. May be nil if the balancer does not wish
|
||||
// to be notified when the RPC completes.
|
||||
Done func(DoneInfo)
|
||||
|
||||
// Metadata provides a way for LB policies to inject arbitrary per-call
|
||||
// metadata. Any metadata returned here will be merged with existing
|
||||
// metadata added by the client application.
|
||||
//
|
||||
// LB policies with child policies are responsible for propagating metadata
|
||||
// injected by their children to the ClientConn, as part of Pick().
|
||||
Metadata metadata.MD
|
||||
}
|
||||
|
||||
// TransientFailureError returns e. It exists for backward compatibility and
|
||||
@@ -335,9 +378,13 @@ type Balancer interface {
|
||||
ResolverError(error)
|
||||
// UpdateSubConnState is called by gRPC when the state of a SubConn
|
||||
// changes.
|
||||
//
|
||||
// Deprecated: Use NewSubConnOptions.StateListener when creating the
|
||||
// SubConn instead.
|
||||
UpdateSubConnState(SubConn, SubConnState)
|
||||
// Close closes the balancer. The balancer is not required to call
|
||||
// ClientConn.RemoveSubConn for its existing SubConns.
|
||||
// Close closes the balancer. The balancer is not currently required to
|
||||
// call SubConn.Shutdown for its existing SubConns; however, this will be
|
||||
// required in a future release, so it is recommended.
|
||||
Close()
|
||||
}
|
||||
|
||||
@@ -382,15 +429,14 @@ var ErrBadResolverState = errors.New("bad resolver state")
|
||||
type ProducerBuilder interface {
|
||||
// Build creates a Producer. The first parameter is always a
|
||||
// grpc.ClientConnInterface (a type to allow creating RPCs/streams on the
|
||||
// associated SubConn), but is declared as interface{} to avoid a
|
||||
// dependency cycle. Should also return a close function that will be
|
||||
// called when all references to the Producer have been given up.
|
||||
Build(grpcClientConnInterface interface{}) (p Producer, close func())
|
||||
// associated SubConn), but is declared as `any` to avoid a dependency
|
||||
// cycle. Should also return a close function that will be called when all
|
||||
// references to the Producer have been given up.
|
||||
Build(grpcClientConnInterface any) (p Producer, close func())
|
||||
}
|
||||
|
||||
// A Producer is a type shared among potentially many consumers. It is
|
||||
// associated with a SubConn, and an implementation will typically contain
|
||||
// other methods to provide additional functionality, e.g. configuration or
|
||||
// subscription registration.
|
||||
type Producer interface {
|
||||
}
|
||||
type Producer any
|
||||
|
22
vendor/google.golang.org/grpc/balancer/base/balancer.go
generated
vendored
22
vendor/google.golang.org/grpc/balancer/base/balancer.go
generated
vendored
@@ -105,7 +105,12 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||
addrsSet.Set(a, nil)
|
||||
if _, ok := b.subConns.Get(a); !ok {
|
||||
// a is a new address (not existing in b.subConns).
|
||||
sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
|
||||
var sc balancer.SubConn
|
||||
opts := balancer.NewSubConnOptions{
|
||||
HealthCheckEnabled: b.config.HealthCheck,
|
||||
StateListener: func(scs balancer.SubConnState) { b.updateSubConnState(sc, scs) },
|
||||
}
|
||||
sc, err := b.cc.NewSubConn([]resolver.Address{a}, opts)
|
||||
if err != nil {
|
||||
logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
|
||||
continue
|
||||
@@ -121,10 +126,10 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||
sc := sci.(balancer.SubConn)
|
||||
// a was removed by resolver.
|
||||
if _, ok := addrsSet.Get(a); !ok {
|
||||
b.cc.RemoveSubConn(sc)
|
||||
sc.Shutdown()
|
||||
b.subConns.Delete(a)
|
||||
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
|
||||
// The entry will be deleted in UpdateSubConnState.
|
||||
// The entry will be deleted in updateSubConnState.
|
||||
}
|
||||
}
|
||||
// If resolver state contains no addresses, return an error so ClientConn
|
||||
@@ -177,7 +182,12 @@ func (b *baseBalancer) regeneratePicker() {
|
||||
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
|
||||
}
|
||||
|
||||
// UpdateSubConnState is a nop because a StateListener is always set in NewSubConn.
|
||||
func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
logger.Errorf("base.baseBalancer: UpdateSubConnState(%v, %+v) called unexpectedly", sc, state)
|
||||
}
|
||||
|
||||
func (b *baseBalancer) updateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
s := state.ConnectivityState
|
||||
if logger.V(2) {
|
||||
logger.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
|
||||
@@ -204,8 +214,8 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
|
||||
case connectivity.Idle:
|
||||
sc.Connect()
|
||||
case connectivity.Shutdown:
|
||||
// When an address was removed by resolver, b called RemoveSubConn but
|
||||
// kept the sc's state in scStates. Remove state for this sc here.
|
||||
// When an address was removed by resolver, b called Shutdown but kept
|
||||
// the sc's state in scStates. Remove state for this sc here.
|
||||
delete(b.scStates, sc)
|
||||
case connectivity.TransientFailure:
|
||||
// Save error to be reported via picker.
|
||||
@@ -226,7 +236,7 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
|
||||
}
|
||||
|
||||
// Close is a nop because base balancer doesn't have internal state to clean up,
|
||||
// and it doesn't need to call RemoveSubConn for the SubConns.
|
||||
// and it doesn't need to call Shutdown for the SubConns.
|
||||
func (b *baseBalancer) Close() {
|
||||
}
|
||||
|
||||
|
481
vendor/google.golang.org/grpc/balancer_conn_wrappers.go
generated
vendored
481
vendor/google.golang.org/grpc/balancer_conn_wrappers.go
generated
vendored
@@ -1,481 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/internal/balancer/gracefulswitch"
|
||||
"google.golang.org/grpc/internal/buffer"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// ccBalancerWrapper sits between the ClientConn and the Balancer.
|
||||
//
|
||||
// ccBalancerWrapper implements methods corresponding to the ones on the
|
||||
// balancer.Balancer interface. The ClientConn is free to call these methods
|
||||
// concurrently and the ccBalancerWrapper ensures that calls from the ClientConn
|
||||
// to the Balancer happen synchronously and in order.
|
||||
//
|
||||
// ccBalancerWrapper also implements the balancer.ClientConn interface and is
|
||||
// passed to the Balancer implementations. It invokes unexported methods on the
|
||||
// ClientConn to handle these calls from the Balancer.
|
||||
//
|
||||
// It uses the gracefulswitch.Balancer internally to ensure that balancer
|
||||
// switches happen in a graceful manner.
|
||||
type ccBalancerWrapper struct {
|
||||
cc *ClientConn
|
||||
|
||||
// Since these fields are accessed only from handleXxx() methods which are
|
||||
// synchronized by the watcher goroutine, we do not need a mutex to protect
|
||||
// these fields.
|
||||
balancer *gracefulswitch.Balancer
|
||||
curBalancerName string
|
||||
|
||||
updateCh *buffer.Unbounded // Updates written on this channel are processed by watcher().
|
||||
resultCh *buffer.Unbounded // Results of calls to UpdateClientConnState() are pushed here.
|
||||
closed *grpcsync.Event // Indicates if close has been called.
|
||||
done *grpcsync.Event // Indicates if close has completed its work.
|
||||
}
|
||||
|
||||
// newCCBalancerWrapper creates a new balancer wrapper. The underlying balancer
|
||||
// is not created until the switchTo() method is invoked.
|
||||
func newCCBalancerWrapper(cc *ClientConn, bopts balancer.BuildOptions) *ccBalancerWrapper {
|
||||
ccb := &ccBalancerWrapper{
|
||||
cc: cc,
|
||||
updateCh: buffer.NewUnbounded(),
|
||||
resultCh: buffer.NewUnbounded(),
|
||||
closed: grpcsync.NewEvent(),
|
||||
done: grpcsync.NewEvent(),
|
||||
}
|
||||
go ccb.watcher()
|
||||
ccb.balancer = gracefulswitch.NewBalancer(ccb, bopts)
|
||||
return ccb
|
||||
}
|
||||
|
||||
// The following xxxUpdate structs wrap the arguments received as part of the
|
||||
// corresponding update. The watcher goroutine uses the 'type' of the update to
|
||||
// invoke the appropriate handler routine to handle the update.
|
||||
|
||||
type ccStateUpdate struct {
|
||||
ccs *balancer.ClientConnState
|
||||
}
|
||||
|
||||
type scStateUpdate struct {
|
||||
sc balancer.SubConn
|
||||
state connectivity.State
|
||||
err error
|
||||
}
|
||||
|
||||
type exitIdleUpdate struct{}
|
||||
|
||||
type resolverErrorUpdate struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type switchToUpdate struct {
|
||||
name string
|
||||
}
|
||||
|
||||
type subConnUpdate struct {
|
||||
acbw *acBalancerWrapper
|
||||
}
|
||||
|
||||
// watcher is a long-running goroutine which reads updates from a channel and
|
||||
// invokes corresponding methods on the underlying balancer. It ensures that
|
||||
// these methods are invoked in a synchronous fashion. It also ensures that
|
||||
// these methods are invoked in the order in which the updates were received.
|
||||
func (ccb *ccBalancerWrapper) watcher() {
|
||||
for {
|
||||
select {
|
||||
case u := <-ccb.updateCh.Get():
|
||||
ccb.updateCh.Load()
|
||||
if ccb.closed.HasFired() {
|
||||
break
|
||||
}
|
||||
switch update := u.(type) {
|
||||
case *ccStateUpdate:
|
||||
ccb.handleClientConnStateChange(update.ccs)
|
||||
case *scStateUpdate:
|
||||
ccb.handleSubConnStateChange(update)
|
||||
case *exitIdleUpdate:
|
||||
ccb.handleExitIdle()
|
||||
case *resolverErrorUpdate:
|
||||
ccb.handleResolverError(update.err)
|
||||
case *switchToUpdate:
|
||||
ccb.handleSwitchTo(update.name)
|
||||
case *subConnUpdate:
|
||||
ccb.handleRemoveSubConn(update.acbw)
|
||||
default:
|
||||
logger.Errorf("ccBalancerWrapper.watcher: unknown update %+v, type %T", update, update)
|
||||
}
|
||||
case <-ccb.closed.Done():
|
||||
}
|
||||
|
||||
if ccb.closed.HasFired() {
|
||||
ccb.handleClose()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateClientConnState is invoked by grpc to push a ClientConnState update to
|
||||
// the underlying balancer.
|
||||
//
|
||||
// Unlike other methods invoked by grpc to push updates to the underlying
|
||||
// balancer, this method cannot simply push the update onto the update channel
|
||||
// and return. It needs to return the error returned by the underlying balancer
|
||||
// back to grpc which propagates that to the resolver.
|
||||
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
|
||||
ccb.updateCh.Put(&ccStateUpdate{ccs: ccs})
|
||||
|
||||
var res interface{}
|
||||
select {
|
||||
case res = <-ccb.resultCh.Get():
|
||||
ccb.resultCh.Load()
|
||||
case <-ccb.closed.Done():
|
||||
// Return early if the balancer wrapper is closed while we are waiting for
|
||||
// the underlying balancer to process a ClientConnState update.
|
||||
return nil
|
||||
}
|
||||
// If the returned error is nil, attempting to type assert to error leads to
|
||||
// panic. So, this needs to handled separately.
|
||||
if res == nil {
|
||||
return nil
|
||||
}
|
||||
return res.(error)
|
||||
}
|
||||
|
||||
// handleClientConnStateChange handles a ClientConnState update from the update
|
||||
// channel and invokes the appropriate method on the underlying balancer.
|
||||
//
|
||||
// If the addresses specified in the update contain addresses of type "grpclb"
|
||||
// and the selected LB policy is not "grpclb", these addresses will be filtered
|
||||
// out and ccs will be modified with the updated address list.
|
||||
func (ccb *ccBalancerWrapper) handleClientConnStateChange(ccs *balancer.ClientConnState) {
|
||||
if ccb.curBalancerName != grpclbName {
|
||||
// Filter any grpclb addresses since we don't have the grpclb balancer.
|
||||
var addrs []resolver.Address
|
||||
for _, addr := range ccs.ResolverState.Addresses {
|
||||
if addr.Type == resolver.GRPCLB {
|
||||
continue
|
||||
}
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
ccs.ResolverState.Addresses = addrs
|
||||
}
|
||||
ccb.resultCh.Put(ccb.balancer.UpdateClientConnState(*ccs))
|
||||
}
|
||||
|
||||
// updateSubConnState is invoked by grpc to push a subConn state update to the
|
||||
// underlying balancer.
|
||||
func (ccb *ccBalancerWrapper) updateSubConnState(sc balancer.SubConn, s connectivity.State, err error) {
|
||||
// When updating addresses for a SubConn, if the address in use is not in
|
||||
// the new addresses, the old ac will be tearDown() and a new ac will be
|
||||
// created. tearDown() generates a state change with Shutdown state, we
|
||||
// don't want the balancer to receive this state change. So before
|
||||
// tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
|
||||
// this function will be called with (nil, Shutdown). We don't need to call
|
||||
// balancer method in this case.
|
||||
if sc == nil {
|
||||
return
|
||||
}
|
||||
ccb.updateCh.Put(&scStateUpdate{
|
||||
sc: sc,
|
||||
state: s,
|
||||
err: err,
|
||||
})
|
||||
}
|
||||
|
||||
// handleSubConnStateChange handles a SubConnState update from the update
|
||||
// channel and invokes the appropriate method on the underlying balancer.
|
||||
func (ccb *ccBalancerWrapper) handleSubConnStateChange(update *scStateUpdate) {
|
||||
ccb.balancer.UpdateSubConnState(update.sc, balancer.SubConnState{ConnectivityState: update.state, ConnectionError: update.err})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) exitIdle() {
|
||||
ccb.updateCh.Put(&exitIdleUpdate{})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) handleExitIdle() {
|
||||
if ccb.cc.GetState() != connectivity.Idle {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ExitIdle()
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) resolverError(err error) {
|
||||
ccb.updateCh.Put(&resolverErrorUpdate{err: err})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) handleResolverError(err error) {
|
||||
ccb.balancer.ResolverError(err)
|
||||
}
|
||||
|
||||
// switchTo is invoked by grpc to instruct the balancer wrapper to switch to the
|
||||
// LB policy identified by name.
|
||||
//
|
||||
// ClientConn calls newCCBalancerWrapper() at creation time. Upon receipt of the
|
||||
// first good update from the name resolver, it determines the LB policy to use
|
||||
// and invokes the switchTo() method. Upon receipt of every subsequent update
|
||||
// from the name resolver, it invokes this method.
|
||||
//
|
||||
// the ccBalancerWrapper keeps track of the current LB policy name, and skips
|
||||
// the graceful balancer switching process if the name does not change.
|
||||
func (ccb *ccBalancerWrapper) switchTo(name string) {
|
||||
ccb.updateCh.Put(&switchToUpdate{name: name})
|
||||
}
|
||||
|
||||
// handleSwitchTo handles a balancer switch update from the update channel. It
|
||||
// calls the SwitchTo() method on the gracefulswitch.Balancer with a
|
||||
// balancer.Builder corresponding to name. If no balancer.Builder is registered
|
||||
// for the given name, it uses the default LB policy which is "pick_first".
|
||||
func (ccb *ccBalancerWrapper) handleSwitchTo(name string) {
|
||||
// TODO: Other languages use case-insensitive balancer registries. We should
|
||||
// switch as well. See: https://github.com/grpc/grpc-go/issues/5288.
|
||||
if strings.EqualFold(ccb.curBalancerName, name) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Ensure that name is a registered LB policy when we get here.
|
||||
// We currently only validate the `loadBalancingConfig` field. We need to do
|
||||
// the same for the `loadBalancingPolicy` field and reject the service config
|
||||
// if the specified policy is not registered.
|
||||
builder := balancer.Get(name)
|
||||
if builder == nil {
|
||||
channelz.Warningf(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q, since the specified LB policy %q was not registered", PickFirstBalancerName, name)
|
||||
builder = newPickfirstBuilder()
|
||||
} else {
|
||||
channelz.Infof(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q", name)
|
||||
}
|
||||
|
||||
if err := ccb.balancer.SwitchTo(builder); err != nil {
|
||||
channelz.Errorf(logger, ccb.cc.channelzID, "Channel failed to build new LB policy %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
ccb.curBalancerName = builder.Name()
|
||||
}
|
||||
|
||||
// handleRemoveSucConn handles a request from the underlying balancer to remove
|
||||
// a subConn.
|
||||
//
|
||||
// See comments in RemoveSubConn() for more details.
|
||||
func (ccb *ccBalancerWrapper) handleRemoveSubConn(acbw *acBalancerWrapper) {
|
||||
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) close() {
|
||||
ccb.closed.Fire()
|
||||
<-ccb.done.Done()
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) handleClose() {
|
||||
ccb.balancer.Close()
|
||||
ccb.done.Fire()
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
if len(addrs) <= 0 {
|
||||
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
|
||||
}
|
||||
ac, err := ccb.cc.newAddrConn(addrs, opts)
|
||||
if err != nil {
|
||||
channelz.Warningf(logger, ccb.cc.channelzID, "acBalancerWrapper: NewSubConn: failed to newAddrConn: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
acbw := &acBalancerWrapper{ac: ac, producers: make(map[balancer.ProducerBuilder]*refCountedProducer)}
|
||||
acbw.ac.mu.Lock()
|
||||
ac.acbw = acbw
|
||||
acbw.ac.mu.Unlock()
|
||||
return acbw, nil
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||
// Before we switched the ccBalancerWrapper to use gracefulswitch.Balancer, it
|
||||
// was required to handle the RemoveSubConn() method asynchronously by pushing
|
||||
// the update onto the update channel. This was done to avoid a deadlock as
|
||||
// switchBalancer() was holding cc.mu when calling Close() on the old
|
||||
// balancer, which would in turn call RemoveSubConn().
|
||||
//
|
||||
// With the use of gracefulswitch.Balancer in ccBalancerWrapper, handling this
|
||||
// asynchronously is probably not required anymore since the switchTo() method
|
||||
// handles the balancer switch by pushing the update onto the channel.
|
||||
// TODO(easwars): Handle this inline.
|
||||
acbw, ok := sc.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ccb.updateCh.Put(&subConnUpdate{acbw: acbw})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||
acbw, ok := sc.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
acbw.UpdateAddresses(addrs)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
|
||||
// Update picker before updating state. Even though the ordering here does
|
||||
// not matter, it can lead to multiple calls of Pick in the common start-up
|
||||
// case where we wait for ready and then perform an RPC. If the picker is
|
||||
// updated later, we could call the "connecting" picker when the state is
|
||||
// updated, and then call the "ready" picker after the picker gets updated.
|
||||
ccb.cc.blockingpicker.updatePicker(s.Picker)
|
||||
ccb.cc.csMgr.updateState(s.ConnectivityState)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOptions) {
|
||||
ccb.cc.resolveNow(o)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) Target() string {
|
||||
return ccb.cc.target
|
||||
}
|
||||
|
||||
// acBalancerWrapper is a wrapper on top of ac for balancers.
|
||||
// It implements balancer.SubConn interface.
|
||||
type acBalancerWrapper struct {
|
||||
mu sync.Mutex
|
||||
ac *addrConn
|
||||
producers map[balancer.ProducerBuilder]*refCountedProducer
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
if len(addrs) <= 0 {
|
||||
acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||
return
|
||||
}
|
||||
if !acbw.ac.tryUpdateAddrs(addrs) {
|
||||
cc := acbw.ac.cc
|
||||
opts := acbw.ac.scopts
|
||||
acbw.ac.mu.Lock()
|
||||
// Set old ac.acbw to nil so the Shutdown state update will be ignored
|
||||
// by balancer.
|
||||
//
|
||||
// TODO(bar) the state transition could be wrong when tearDown() old ac
|
||||
// and creating new ac, fix the transition.
|
||||
acbw.ac.acbw = nil
|
||||
acbw.ac.mu.Unlock()
|
||||
acState := acbw.ac.getState()
|
||||
acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||
|
||||
if acState == connectivity.Shutdown {
|
||||
return
|
||||
}
|
||||
|
||||
newAC, err := cc.newAddrConn(addrs, opts)
|
||||
if err != nil {
|
||||
channelz.Warningf(logger, acbw.ac.channelzID, "acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
|
||||
return
|
||||
}
|
||||
acbw.ac = newAC
|
||||
newAC.mu.Lock()
|
||||
newAC.acbw = acbw
|
||||
newAC.mu.Unlock()
|
||||
if acState != connectivity.Idle {
|
||||
go newAC.connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Connect() {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
go acbw.ac.connect()
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
return acbw.ac
|
||||
}
|
||||
|
||||
var errSubConnNotReady = status.Error(codes.Unavailable, "SubConn not currently connected")
|
||||
|
||||
// NewStream begins a streaming RPC on the addrConn. If the addrConn is not
|
||||
// ready, returns errSubConnNotReady.
|
||||
func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
|
||||
transport := acbw.ac.getReadyTransport()
|
||||
if transport == nil {
|
||||
return nil, errSubConnNotReady
|
||||
}
|
||||
return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...)
|
||||
}
|
||||
|
||||
// Invoke performs a unary RPC. If the addrConn is not ready, returns
|
||||
// errSubConnNotReady.
|
||||
func (acbw *acBalancerWrapper) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, opts ...CallOption) error {
|
||||
cs, err := acbw.NewStream(ctx, unaryStreamDesc, method, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cs.SendMsg(args); err != nil {
|
||||
return err
|
||||
}
|
||||
return cs.RecvMsg(reply)
|
||||
}
|
||||
|
||||
type refCountedProducer struct {
|
||||
producer balancer.Producer
|
||||
refs int // number of current refs to the producer
|
||||
close func() // underlying producer's close function
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) (balancer.Producer, func()) {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
|
||||
// Look up existing producer from this builder.
|
||||
pData := acbw.producers[pb]
|
||||
if pData == nil {
|
||||
// Not found; create a new one and add it to the producers map.
|
||||
p, close := pb.Build(acbw)
|
||||
pData = &refCountedProducer{producer: p, close: close}
|
||||
acbw.producers[pb] = pData
|
||||
}
|
||||
// Account for this new reference.
|
||||
pData.refs++
|
||||
|
||||
// Return a cleanup function wrapped in a OnceFunc to remove this reference
|
||||
// and delete the refCountedProducer from the map if the total reference
|
||||
// count goes to zero.
|
||||
unref := func() {
|
||||
acbw.mu.Lock()
|
||||
pData.refs--
|
||||
if pData.refs == 0 {
|
||||
defer pData.close() // Run outside the acbw mutex
|
||||
delete(acbw.producers, pb)
|
||||
}
|
||||
acbw.mu.Unlock()
|
||||
}
|
||||
return pData.producer, grpcsync.OnceFunc(unref)
|
||||
}
|
380
vendor/google.golang.org/grpc/balancer_wrapper.go
generated
vendored
Normal file
380
vendor/google.golang.org/grpc/balancer_wrapper.go
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/internal/balancer/gracefulswitch"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// ccBalancerWrapper sits between the ClientConn and the Balancer.
|
||||
//
|
||||
// ccBalancerWrapper implements methods corresponding to the ones on the
|
||||
// balancer.Balancer interface. The ClientConn is free to call these methods
|
||||
// concurrently and the ccBalancerWrapper ensures that calls from the ClientConn
|
||||
// to the Balancer happen in order by performing them in the serializer, without
|
||||
// any mutexes held.
|
||||
//
|
||||
// ccBalancerWrapper also implements the balancer.ClientConn interface and is
|
||||
// passed to the Balancer implementations. It invokes unexported methods on the
|
||||
// ClientConn to handle these calls from the Balancer.
|
||||
//
|
||||
// It uses the gracefulswitch.Balancer internally to ensure that balancer
|
||||
// switches happen in a graceful manner.
|
||||
type ccBalancerWrapper struct {
|
||||
// The following fields are initialized when the wrapper is created and are
|
||||
// read-only afterwards, and therefore can be accessed without a mutex.
|
||||
cc *ClientConn
|
||||
opts balancer.BuildOptions
|
||||
serializer *grpcsync.CallbackSerializer
|
||||
serializerCancel context.CancelFunc
|
||||
|
||||
// The following fields are only accessed within the serializer or during
|
||||
// initialization.
|
||||
curBalancerName string
|
||||
balancer *gracefulswitch.Balancer
|
||||
|
||||
// The following field is protected by mu. Caller must take cc.mu before
|
||||
// taking mu.
|
||||
mu sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
// newCCBalancerWrapper creates a new balancer wrapper in idle state. The
|
||||
// underlying balancer is not created until the switchTo() method is invoked.
|
||||
func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper {
|
||||
ctx, cancel := context.WithCancel(cc.ctx)
|
||||
ccb := &ccBalancerWrapper{
|
||||
cc: cc,
|
||||
opts: balancer.BuildOptions{
|
||||
DialCreds: cc.dopts.copts.TransportCredentials,
|
||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||
Dialer: cc.dopts.copts.Dialer,
|
||||
Authority: cc.authority,
|
||||
CustomUserAgent: cc.dopts.copts.UserAgent,
|
||||
ChannelzParentID: cc.channelzID,
|
||||
Target: cc.parsedTarget,
|
||||
},
|
||||
serializer: grpcsync.NewCallbackSerializer(ctx),
|
||||
serializerCancel: cancel,
|
||||
}
|
||||
ccb.balancer = gracefulswitch.NewBalancer(ccb, ccb.opts)
|
||||
return ccb
|
||||
}
|
||||
|
||||
// updateClientConnState is invoked by grpc to push a ClientConnState update to
|
||||
// the underlying balancer. This is always executed from the serializer, so
|
||||
// it is safe to call into the balancer here.
|
||||
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
|
||||
errCh := make(chan error)
|
||||
ok := ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
defer close(errCh)
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
err := ccb.balancer.UpdateClientConnState(*ccs)
|
||||
if logger.V(2) && err != nil {
|
||||
logger.Infof("error from balancer.UpdateClientConnState: %v", err)
|
||||
}
|
||||
errCh <- err
|
||||
})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
// resolverError is invoked by grpc to push a resolver error to the underlying
|
||||
// balancer. The call to the balancer is executed from the serializer.
|
||||
func (ccb *ccBalancerWrapper) resolverError(err error) {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ResolverError(err)
|
||||
})
|
||||
}
|
||||
|
||||
// switchTo is invoked by grpc to instruct the balancer wrapper to switch to the
|
||||
// LB policy identified by name.
|
||||
//
|
||||
// ClientConn calls newCCBalancerWrapper() at creation time. Upon receipt of the
|
||||
// first good update from the name resolver, it determines the LB policy to use
|
||||
// and invokes the switchTo() method. Upon receipt of every subsequent update
|
||||
// from the name resolver, it invokes this method.
|
||||
//
|
||||
// the ccBalancerWrapper keeps track of the current LB policy name, and skips
|
||||
// the graceful balancer switching process if the name does not change.
|
||||
func (ccb *ccBalancerWrapper) switchTo(name string) {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
// TODO: Other languages use case-sensitive balancer registries. We should
|
||||
// switch as well. See: https://github.com/grpc/grpc-go/issues/5288.
|
||||
if strings.EqualFold(ccb.curBalancerName, name) {
|
||||
return
|
||||
}
|
||||
ccb.buildLoadBalancingPolicy(name)
|
||||
})
|
||||
}
|
||||
|
||||
// buildLoadBalancingPolicy performs the following:
|
||||
// - retrieve a balancer builder for the given name. Use the default LB
|
||||
// policy, pick_first, if no LB policy with name is found in the registry.
|
||||
// - instruct the gracefulswitch balancer to switch to the above builder. This
|
||||
// will actually build the new balancer.
|
||||
// - update the `curBalancerName` field
|
||||
//
|
||||
// Must be called from a serializer callback.
|
||||
func (ccb *ccBalancerWrapper) buildLoadBalancingPolicy(name string) {
|
||||
builder := balancer.Get(name)
|
||||
if builder == nil {
|
||||
channelz.Warningf(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q, since the specified LB policy %q was not registered", PickFirstBalancerName, name)
|
||||
builder = newPickfirstBuilder()
|
||||
} else {
|
||||
channelz.Infof(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q", name)
|
||||
}
|
||||
|
||||
if err := ccb.balancer.SwitchTo(builder); err != nil {
|
||||
channelz.Errorf(logger, ccb.cc.channelzID, "Channel failed to build new LB policy %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
ccb.curBalancerName = builder.Name()
|
||||
}
|
||||
|
||||
// close initiates async shutdown of the wrapper. cc.mu must be held when
|
||||
// calling this function. To determine the wrapper has finished shutting down,
|
||||
// the channel should block on ccb.serializer.Done() without cc.mu held.
|
||||
func (ccb *ccBalancerWrapper) close() {
|
||||
ccb.mu.Lock()
|
||||
ccb.closed = true
|
||||
ccb.mu.Unlock()
|
||||
channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: closing")
|
||||
ccb.serializer.Schedule(func(context.Context) {
|
||||
if ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.Close()
|
||||
ccb.balancer = nil
|
||||
})
|
||||
ccb.serializerCancel()
|
||||
}
|
||||
|
||||
// exitIdle invokes the balancer's exitIdle method in the serializer.
|
||||
func (ccb *ccBalancerWrapper) exitIdle() {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ExitIdle()
|
||||
})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
ccb.cc.mu.Lock()
|
||||
defer ccb.cc.mu.Unlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return nil, fmt.Errorf("balancer is being closed; no new SubConns allowed")
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
|
||||
if len(addrs) == 0 {
|
||||
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
|
||||
}
|
||||
ac, err := ccb.cc.newAddrConnLocked(addrs, opts)
|
||||
if err != nil {
|
||||
channelz.Warningf(logger, ccb.cc.channelzID, "acBalancerWrapper: NewSubConn: failed to newAddrConn: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
acbw := &acBalancerWrapper{
|
||||
ccb: ccb,
|
||||
ac: ac,
|
||||
producers: make(map[balancer.ProducerBuilder]*refCountedProducer),
|
||||
stateListener: opts.StateListener,
|
||||
}
|
||||
ac.acbw = acbw
|
||||
return acbw, nil
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||
// The graceful switch balancer will never call this.
|
||||
logger.Errorf("ccb RemoveSubConn(%v) called unexpectedly, sc")
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||
acbw, ok := sc.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
acbw.UpdateAddresses(addrs)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
|
||||
ccb.cc.mu.Lock()
|
||||
defer ccb.cc.mu.Unlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
// Update picker before updating state. Even though the ordering here does
|
||||
// not matter, it can lead to multiple calls of Pick in the common start-up
|
||||
// case where we wait for ready and then perform an RPC. If the picker is
|
||||
// updated later, we could call the "connecting" picker when the state is
|
||||
// updated, and then call the "ready" picker after the picker gets updated.
|
||||
|
||||
// Note that there is no need to check if the balancer wrapper was closed,
|
||||
// as we know the graceful switch LB policy will not call cc if it has been
|
||||
// closed.
|
||||
ccb.cc.pickerWrapper.updatePicker(s.Picker)
|
||||
ccb.cc.csMgr.updateState(s.ConnectivityState)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOptions) {
|
||||
ccb.cc.mu.RLock()
|
||||
defer ccb.cc.mu.RUnlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
ccb.cc.resolveNowLocked(o)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) Target() string {
|
||||
return ccb.cc.target
|
||||
}
|
||||
|
||||
// acBalancerWrapper is a wrapper on top of ac for balancers.
|
||||
// It implements balancer.SubConn interface.
|
||||
type acBalancerWrapper struct {
|
||||
ac *addrConn // read-only
|
||||
ccb *ccBalancerWrapper // read-only
|
||||
stateListener func(balancer.SubConnState)
|
||||
|
||||
mu sync.Mutex
|
||||
producers map[balancer.ProducerBuilder]*refCountedProducer
|
||||
}
|
||||
|
||||
// updateState is invoked by grpc to push a subConn state update to the
|
||||
// underlying balancer.
|
||||
func (acbw *acBalancerWrapper) updateState(s connectivity.State, err error) {
|
||||
acbw.ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || acbw.ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
// Even though it is optional for balancers, gracefulswitch ensures
|
||||
// opts.StateListener is set, so this cannot ever be nil.
|
||||
// TODO: delete this comment when UpdateSubConnState is removed.
|
||||
acbw.stateListener(balancer.SubConnState{ConnectivityState: s, ConnectionError: err})
|
||||
})
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) String() string {
|
||||
return fmt.Sprintf("SubConn(id:%d)", acbw.ac.channelzID.Int())
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
|
||||
acbw.ac.updateAddrs(addrs)
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Connect() {
|
||||
go acbw.ac.connect()
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Shutdown() {
|
||||
acbw.ccb.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||
}
|
||||
|
||||
// NewStream begins a streaming RPC on the addrConn. If the addrConn is not
|
||||
// ready, blocks until it is or ctx expires. Returns an error when the context
|
||||
// expires or the addrConn is shut down.
|
||||
func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
|
||||
transport, err := acbw.ac.getTransport(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...)
|
||||
}
|
||||
|
||||
// Invoke performs a unary RPC. If the addrConn is not ready, returns
|
||||
// errSubConnNotReady.
|
||||
func (acbw *acBalancerWrapper) Invoke(ctx context.Context, method string, args any, reply any, opts ...CallOption) error {
|
||||
cs, err := acbw.NewStream(ctx, unaryStreamDesc, method, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cs.SendMsg(args); err != nil {
|
||||
return err
|
||||
}
|
||||
return cs.RecvMsg(reply)
|
||||
}
|
||||
|
||||
type refCountedProducer struct {
|
||||
producer balancer.Producer
|
||||
refs int // number of current refs to the producer
|
||||
close func() // underlying producer's close function
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) (balancer.Producer, func()) {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
|
||||
// Look up existing producer from this builder.
|
||||
pData := acbw.producers[pb]
|
||||
if pData == nil {
|
||||
// Not found; create a new one and add it to the producers map.
|
||||
p, close := pb.Build(acbw)
|
||||
pData = &refCountedProducer{producer: p, close: close}
|
||||
acbw.producers[pb] = pData
|
||||
}
|
||||
// Account for this new reference.
|
||||
pData.refs++
|
||||
|
||||
// Return a cleanup function wrapped in a OnceFunc to remove this reference
|
||||
// and delete the refCountedProducer from the map if the total reference
|
||||
// count goes to zero.
|
||||
unref := func() {
|
||||
acbw.mu.Lock()
|
||||
pData.refs--
|
||||
if pData.refs == 0 {
|
||||
defer pData.close() // Run outside the acbw mutex
|
||||
delete(acbw.producers, pb)
|
||||
}
|
||||
acbw.mu.Unlock()
|
||||
}
|
||||
return pData.producer, grpcsync.OnceFunc(unref)
|
||||
}
|
9
vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
generated
vendored
9
vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
generated
vendored
@@ -18,14 +18,13 @@
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc v3.14.0
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.22.0
|
||||
// source: grpc/binlog/v1/binarylog.proto
|
||||
|
||||
package grpc_binarylog_v1
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
durationpb "google.golang.org/protobuf/types/known/durationpb"
|
||||
@@ -41,10 +40,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
// Enumerates the type of event
|
||||
// Note the terminology is different from the RPC semantics
|
||||
// definition, but the same meaning is expressed here.
|
||||
|
6
vendor/google.golang.org/grpc/call.go
generated
vendored
6
vendor/google.golang.org/grpc/call.go
generated
vendored
@@ -26,7 +26,7 @@ import (
|
||||
// received. This is typically called by generated code.
|
||||
//
|
||||
// All errors returned by Invoke are compatible with the status package.
|
||||
func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
|
||||
func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply any, opts ...CallOption) error {
|
||||
// allow interceptor to see all applicable call options, which means those
|
||||
// configured as defaults from dial option as well as per-call options
|
||||
opts = combine(cc.dopts.callOptions, opts)
|
||||
@@ -56,13 +56,13 @@ func combine(o1 []CallOption, o2 []CallOption) []CallOption {
|
||||
// received. This is typically called by generated code.
|
||||
//
|
||||
// DEPRECATED: Use ClientConn.Invoke instead.
|
||||
func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
|
||||
func Invoke(ctx context.Context, method string, args, reply any, cc *ClientConn, opts ...CallOption) error {
|
||||
return cc.Invoke(ctx, method, args, reply, opts...)
|
||||
}
|
||||
|
||||
var unaryStreamDesc = &StreamDesc{ServerStreams: false, ClientStreams: false}
|
||||
|
||||
func invoke(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error {
|
||||
func invoke(ctx context.Context, method string, req, reply any, cc *ClientConn, opts ...CallOption) error {
|
||||
cs, err := newClientStream(ctx, unaryStreamDesc, cc, method, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
|
971
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
971
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
File diff suppressed because it is too large
Load Diff
8
vendor/google.golang.org/grpc/codec.go
generated
vendored
8
vendor/google.golang.org/grpc/codec.go
generated
vendored
@@ -27,8 +27,8 @@ import (
|
||||
// omits the name/string, which vary between the two and are not needed for
|
||||
// anything besides the registry in the encoding package.
|
||||
type baseCodec interface {
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Marshal(v any) ([]byte, error)
|
||||
Unmarshal(data []byte, v any) error
|
||||
}
|
||||
|
||||
var _ baseCodec = Codec(nil)
|
||||
@@ -41,9 +41,9 @@ var _ baseCodec = encoding.Codec(nil)
|
||||
// Deprecated: use encoding.Codec instead.
|
||||
type Codec interface {
|
||||
// Marshal returns the wire format of v.
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
Marshal(v any) ([]byte, error)
|
||||
// Unmarshal parses the wire format into v.
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Unmarshal(data []byte, v any) error
|
||||
// String returns the name of the Codec implementation. This is unused by
|
||||
// gRPC.
|
||||
String() string
|
||||
|
51
vendor/google.golang.org/grpc/codes/code_string.go
generated
vendored
51
vendor/google.golang.org/grpc/codes/code_string.go
generated
vendored
@@ -18,7 +18,15 @@
|
||||
|
||||
package codes
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
internal.CanonicalString = canonicalString
|
||||
}
|
||||
|
||||
func (c Code) String() string {
|
||||
switch c {
|
||||
@@ -60,3 +68,44 @@ func (c Code) String() string {
|
||||
return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
|
||||
}
|
||||
}
|
||||
|
||||
func canonicalString(c Code) string {
|
||||
switch c {
|
||||
case OK:
|
||||
return "OK"
|
||||
case Canceled:
|
||||
return "CANCELLED"
|
||||
case Unknown:
|
||||
return "UNKNOWN"
|
||||
case InvalidArgument:
|
||||
return "INVALID_ARGUMENT"
|
||||
case DeadlineExceeded:
|
||||
return "DEADLINE_EXCEEDED"
|
||||
case NotFound:
|
||||
return "NOT_FOUND"
|
||||
case AlreadyExists:
|
||||
return "ALREADY_EXISTS"
|
||||
case PermissionDenied:
|
||||
return "PERMISSION_DENIED"
|
||||
case ResourceExhausted:
|
||||
return "RESOURCE_EXHAUSTED"
|
||||
case FailedPrecondition:
|
||||
return "FAILED_PRECONDITION"
|
||||
case Aborted:
|
||||
return "ABORTED"
|
||||
case OutOfRange:
|
||||
return "OUT_OF_RANGE"
|
||||
case Unimplemented:
|
||||
return "UNIMPLEMENTED"
|
||||
case Internal:
|
||||
return "INTERNAL"
|
||||
case Unavailable:
|
||||
return "UNAVAILABLE"
|
||||
case DataLoss:
|
||||
return "DATA_LOSS"
|
||||
case Unauthenticated:
|
||||
return "UNAUTHENTICATED"
|
||||
default:
|
||||
return "CODE(" + strconv.FormatInt(int64(c), 10) + ")"
|
||||
}
|
||||
}
|
||||
|
8
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
8
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
@@ -25,7 +25,13 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
|
||||
// A Code is a status code defined according to the [gRPC documentation].
|
||||
//
|
||||
// Only the codes defined as consts in this package are valid codes. Do not use
|
||||
// other code values. Behavior of other codes is implementation-specific and
|
||||
// interoperability between implementations is not guaranteed.
|
||||
//
|
||||
// [gRPC documentation]: https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
|
||||
type Code uint32
|
||||
|
||||
const (
|
||||
|
79
vendor/google.golang.org/grpc/credentials/tls.go
generated
vendored
79
vendor/google.golang.org/grpc/credentials/tls.go
generated
vendored
@@ -23,9 +23,9 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
credinternal "google.golang.org/grpc/internal/credentials"
|
||||
)
|
||||
@@ -44,10 +44,25 @@ func (t TLSInfo) AuthType() string {
|
||||
return "tls"
|
||||
}
|
||||
|
||||
// cipherSuiteLookup returns the string version of a TLS cipher suite ID.
|
||||
func cipherSuiteLookup(cipherSuiteID uint16) string {
|
||||
for _, s := range tls.CipherSuites() {
|
||||
if s.ID == cipherSuiteID {
|
||||
return s.Name
|
||||
}
|
||||
}
|
||||
for _, s := range tls.InsecureCipherSuites() {
|
||||
if s.ID == cipherSuiteID {
|
||||
return s.Name
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("unknown ID: %v", cipherSuiteID)
|
||||
}
|
||||
|
||||
// GetSecurityValue returns security info requested by channelz.
|
||||
func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
|
||||
v := &TLSChannelzSecurityValue{
|
||||
StandardName: cipherSuiteLookup[t.State.CipherSuite],
|
||||
StandardName: cipherSuiteLookup(t.State.CipherSuite),
|
||||
}
|
||||
// Currently there's no way to get LocalCertificate info from tls package.
|
||||
if len(t.State.PeerCertificates) > 0 {
|
||||
@@ -138,10 +153,39 @@ func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// The following cipher suites are forbidden for use with HTTP/2 by
|
||||
// https://datatracker.ietf.org/doc/html/rfc7540#appendix-A
|
||||
var tls12ForbiddenCipherSuites = map[uint16]struct{}{
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: {},
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: {},
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: {},
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {},
|
||||
}
|
||||
|
||||
// NewTLS uses c to construct a TransportCredentials based on TLS.
|
||||
func NewTLS(c *tls.Config) TransportCredentials {
|
||||
tc := &tlsCreds{credinternal.CloneTLSConfig(c)}
|
||||
tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos)
|
||||
// If the user did not configure a MinVersion and did not configure a
|
||||
// MaxVersion < 1.2, use MinVersion=1.2, which is required by
|
||||
// https://datatracker.ietf.org/doc/html/rfc7540#section-9.2
|
||||
if tc.config.MinVersion == 0 && (tc.config.MaxVersion == 0 || tc.config.MaxVersion >= tls.VersionTLS12) {
|
||||
tc.config.MinVersion = tls.VersionTLS12
|
||||
}
|
||||
// If the user did not configure CipherSuites, use all "secure" cipher
|
||||
// suites reported by the TLS package, but remove some explicitly forbidden
|
||||
// by https://datatracker.ietf.org/doc/html/rfc7540#appendix-A
|
||||
if tc.config.CipherSuites == nil {
|
||||
for _, cs := range tls.CipherSuites() {
|
||||
if _, ok := tls12ForbiddenCipherSuites[cs.ID]; !ok {
|
||||
tc.config.CipherSuites = append(tc.config.CipherSuites, cs.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return tc
|
||||
}
|
||||
|
||||
@@ -166,7 +210,7 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
|
||||
// it will override the virtual host name of authority (e.g. :authority header
|
||||
// field) in requests.
|
||||
func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
|
||||
b, err := ioutil.ReadFile(certFile)
|
||||
b, err := os.ReadFile(certFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -205,32 +249,3 @@ type TLSChannelzSecurityValue struct {
|
||||
LocalCertificate []byte
|
||||
RemoteCertificate []byte
|
||||
}
|
||||
|
||||
var cipherSuiteLookup = map[uint16]string{
|
||||
tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_FALLBACK_SCSV: "TLS_FALLBACK_SCSV",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256",
|
||||
tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384",
|
||||
tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
|
||||
}
|
||||
|
146
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
146
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
@@ -38,12 +38,15 @@ import (
|
||||
|
||||
func init() {
|
||||
internal.AddGlobalDialOptions = func(opt ...DialOption) {
|
||||
extraDialOptions = append(extraDialOptions, opt...)
|
||||
globalDialOptions = append(globalDialOptions, opt...)
|
||||
}
|
||||
internal.ClearGlobalDialOptions = func() {
|
||||
extraDialOptions = nil
|
||||
globalDialOptions = nil
|
||||
}
|
||||
internal.WithBinaryLogger = withBinaryLogger
|
||||
internal.JoinDialOptions = newJoinDialOption
|
||||
internal.DisableGlobalDialOptions = newDisableGlobalDialOptions
|
||||
internal.WithRecvBufferPool = withRecvBufferPool
|
||||
}
|
||||
|
||||
// dialOptions configure a Dial call. dialOptions are set by the DialOption
|
||||
@@ -61,7 +64,6 @@ type dialOptions struct {
|
||||
block bool
|
||||
returnLastError bool
|
||||
timeout time.Duration
|
||||
scChan <-chan ServiceConfig
|
||||
authority string
|
||||
binaryLogger binarylog.Logger
|
||||
copts transport.ConnectOptions
|
||||
@@ -75,6 +77,8 @@ type dialOptions struct {
|
||||
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
|
||||
defaultServiceConfigRawJSON *string
|
||||
resolvers []resolver.Builder
|
||||
idleTimeout time.Duration
|
||||
recvBufferPool SharedBufferPool
|
||||
}
|
||||
|
||||
// DialOption configures how we set up the connection.
|
||||
@@ -82,7 +86,7 @@ type DialOption interface {
|
||||
apply(*dialOptions)
|
||||
}
|
||||
|
||||
var extraDialOptions []DialOption
|
||||
var globalDialOptions []DialOption
|
||||
|
||||
// EmptyDialOption does not alter the dial configuration. It can be embedded in
|
||||
// another structure to build custom dial options.
|
||||
@@ -95,6 +99,16 @@ type EmptyDialOption struct{}
|
||||
|
||||
func (EmptyDialOption) apply(*dialOptions) {}
|
||||
|
||||
type disableGlobalDialOptions struct{}
|
||||
|
||||
func (disableGlobalDialOptions) apply(*dialOptions) {}
|
||||
|
||||
// newDisableGlobalDialOptions returns a DialOption that prevents the ClientConn
|
||||
// from applying the global DialOptions (set via AddGlobalDialOptions).
|
||||
func newDisableGlobalDialOptions() DialOption {
|
||||
return &disableGlobalDialOptions{}
|
||||
}
|
||||
|
||||
// funcDialOption wraps a function that modifies dialOptions into an
|
||||
// implementation of the DialOption interface.
|
||||
type funcDialOption struct {
|
||||
@@ -111,13 +125,42 @@ func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
|
||||
}
|
||||
}
|
||||
|
||||
type joinDialOption struct {
|
||||
opts []DialOption
|
||||
}
|
||||
|
||||
func (jdo *joinDialOption) apply(do *dialOptions) {
|
||||
for _, opt := range jdo.opts {
|
||||
opt.apply(do)
|
||||
}
|
||||
}
|
||||
|
||||
func newJoinDialOption(opts ...DialOption) DialOption {
|
||||
return &joinDialOption{opts: opts}
|
||||
}
|
||||
|
||||
// WithSharedWriteBuffer allows reusing per-connection transport write buffer.
|
||||
// If this option is set to true every connection will release the buffer after
|
||||
// flushing the data on the wire.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithSharedWriteBuffer(val bool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.SharedWriteBuffer = val
|
||||
})
|
||||
}
|
||||
|
||||
// WithWriteBufferSize determines how much data can be batched before doing a
|
||||
// write on the wire. The corresponding memory allocation for this buffer will
|
||||
// be twice the size to keep syscalls low. The default value for this buffer is
|
||||
// 32KB.
|
||||
//
|
||||
// Zero will disable the write buffer such that each write will be on underlying
|
||||
// connection. Note: A Send call may not directly translate to a write.
|
||||
// Zero or negative values will disable the write buffer such that each write
|
||||
// will be on underlying connection. Note: A Send call may not directly
|
||||
// translate to a write.
|
||||
func WithWriteBufferSize(s int) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.WriteBufferSize = s
|
||||
@@ -127,8 +170,9 @@ func WithWriteBufferSize(s int) DialOption {
|
||||
// WithReadBufferSize lets you set the size of read buffer, this determines how
|
||||
// much data can be read at most for each read syscall.
|
||||
//
|
||||
// The default value for this buffer is 32KB. Zero will disable read buffer for
|
||||
// a connection so data framer can access the underlying conn directly.
|
||||
// The default value for this buffer is 32KB. Zero or negative values will
|
||||
// disable read buffer for a connection so data framer can access the
|
||||
// underlying conn directly.
|
||||
func WithReadBufferSize(s int) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.ReadBufferSize = s
|
||||
@@ -206,19 +250,6 @@ func WithDecompressor(dc Decompressor) DialOption {
|
||||
})
|
||||
}
|
||||
|
||||
// WithServiceConfig returns a DialOption which has a channel to read the
|
||||
// service configuration.
|
||||
//
|
||||
// Deprecated: service config should be received through name resolver or via
|
||||
// WithDefaultServiceConfig, as specified at
|
||||
// https://github.com/grpc/grpc/blob/master/doc/service_config.md. Will be
|
||||
// removed in a future 1.x release.
|
||||
func WithServiceConfig(c <-chan ServiceConfig) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.scChan = c
|
||||
})
|
||||
}
|
||||
|
||||
// WithConnectParams configures the ClientConn to use the provided ConnectParams
|
||||
// for creating and maintaining connections to servers.
|
||||
//
|
||||
@@ -267,6 +298,9 @@ func withBackoff(bs internalbackoff.Strategy) DialOption {
|
||||
// WithBlock returns a DialOption which makes callers of Dial block until the
|
||||
// underlying connection is up. Without this, Dial returns immediately and
|
||||
// connecting the server happens in background.
|
||||
//
|
||||
// Use of this feature is not recommended. For more information, please see:
|
||||
// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
|
||||
func WithBlock() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.block = true
|
||||
@@ -278,6 +312,9 @@ func WithBlock() DialOption {
|
||||
// the context.DeadlineExceeded error.
|
||||
// Implies WithBlock()
|
||||
//
|
||||
// Use of this feature is not recommended. For more information, please see:
|
||||
// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
@@ -363,6 +400,17 @@ func WithTimeout(d time.Duration) DialOption {
|
||||
// connections. If FailOnNonTempDialError() is set to true, and an error is
|
||||
// returned by f, gRPC checks the error's Temporary() method to decide if it
|
||||
// should try to reconnect to the network address.
|
||||
//
|
||||
// Note: All supported releases of Go (as of December 2023) override the OS
|
||||
// defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive
|
||||
// with OS defaults for keepalive time and interval, use a net.Dialer that sets
|
||||
// the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket
|
||||
// option to true from the Control field. For a concrete example of how to do
|
||||
// this, see internal.NetDialerWithTCPKeepalive().
|
||||
//
|
||||
// For more information, please see [issue 23459] in the Go github repo.
|
||||
//
|
||||
// [issue 23459]: https://github.com/golang/go/issues/23459
|
||||
func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.Dialer = f
|
||||
@@ -420,6 +468,9 @@ func withBinaryLogger(bl binarylog.Logger) DialOption {
|
||||
// FailOnNonTempDialError only affects the initial dial, and does not do
|
||||
// anything useful unless you are also using WithBlock().
|
||||
//
|
||||
// Use of this feature is not recommended. For more information, please see:
|
||||
// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
@@ -434,7 +485,7 @@ func FailOnNonTempDialError(f bool) DialOption {
|
||||
// the RPCs.
|
||||
func WithUserAgent(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.UserAgent = s
|
||||
o.copts.UserAgent = s + " " + grpcUA
|
||||
})
|
||||
}
|
||||
|
||||
@@ -584,12 +635,16 @@ func withHealthCheckFunc(f internal.HealthChecker) DialOption {
|
||||
|
||||
func defaultDialOptions() dialOptions {
|
||||
return dialOptions{
|
||||
healthCheckFunc: internal.HealthCheckFunc,
|
||||
copts: transport.ConnectOptions{
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
ReadBufferSize: defaultReadBufSize,
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
UseProxy: true,
|
||||
UserAgent: grpcUA,
|
||||
},
|
||||
bs: internalbackoff.DefaultExponential,
|
||||
healthCheckFunc: internal.HealthCheckFunc,
|
||||
idleTimeout: 30 * time.Minute,
|
||||
recvBufferPool: nopBufferPool{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,3 +673,46 @@ func WithResolvers(rs ...resolver.Builder) DialOption {
|
||||
o.resolvers = append(o.resolvers, rs...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithIdleTimeout returns a DialOption that configures an idle timeout for the
|
||||
// channel. If the channel is idle for the configured timeout, i.e there are no
|
||||
// ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode
|
||||
// and as a result the name resolver and load balancer will be shut down. The
|
||||
// channel will exit idle mode when the Connect() method is called or when an
|
||||
// RPC is initiated.
|
||||
//
|
||||
// A default timeout of 30 minutes will be used if this dial option is not set
|
||||
// at dial time and idleness can be disabled by passing a timeout of zero.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithIdleTimeout(d time.Duration) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.idleTimeout = d
|
||||
})
|
||||
}
|
||||
|
||||
// WithRecvBufferPool returns a DialOption that configures the ClientConn
|
||||
// to use the provided shared buffer pool for parsing incoming messages. Depending
|
||||
// on the application's workload, this could result in reduced memory allocation.
|
||||
//
|
||||
// If you are unsure about how to implement a memory pool but want to utilize one,
|
||||
// begin with grpc.NewSharedBufferPool.
|
||||
//
|
||||
// Note: The shared buffer pool feature will not be active if any of the following
|
||||
// options are used: WithStatsHandler, EnableTracing, or binary logging. In such
|
||||
// cases, the shared buffer pool will be ignored.
|
||||
//
|
||||
// Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in
|
||||
// v1.60.0 or later.
|
||||
func WithRecvBufferPool(bufferPool SharedBufferPool) DialOption {
|
||||
return withRecvBufferPool(bufferPool)
|
||||
}
|
||||
|
||||
func withRecvBufferPool(bufferPool SharedBufferPool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.recvBufferPool = bufferPool
|
||||
})
|
||||
}
|
||||
|
21
vendor/google.golang.org/grpc/encoding/encoding.go
generated
vendored
21
vendor/google.golang.org/grpc/encoding/encoding.go
generated
vendored
@@ -38,6 +38,10 @@ const Identity = "identity"
|
||||
|
||||
// Compressor is used for compressing and decompressing when sending or
|
||||
// receiving messages.
|
||||
//
|
||||
// If a Compressor implements `DecompressedSize(compressedBytes []byte) int`,
|
||||
// gRPC will invoke it to determine the size of the buffer allocated for the
|
||||
// result of decompression. A return value of -1 indicates unknown size.
|
||||
type Compressor interface {
|
||||
// Compress writes the data written to wc to w after compressing it. If an
|
||||
// error occurs while initializing the compressor, that error is returned
|
||||
@@ -51,15 +55,6 @@ type Compressor interface {
|
||||
// coding header. The result must be static; the result cannot change
|
||||
// between calls.
|
||||
Name() string
|
||||
// If a Compressor implements
|
||||
// DecompressedSize(compressedBytes []byte) int, gRPC will call it
|
||||
// to determine the size of the buffer allocated for the result of decompression.
|
||||
// Return -1 to indicate unknown size.
|
||||
//
|
||||
// Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
}
|
||||
|
||||
var registeredCompressor = make(map[string]Compressor)
|
||||
@@ -75,7 +70,9 @@ var registeredCompressor = make(map[string]Compressor)
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func RegisterCompressor(c Compressor) {
|
||||
registeredCompressor[c.Name()] = c
|
||||
grpcutil.RegisteredCompressorNames = append(grpcutil.RegisteredCompressorNames, c.Name())
|
||||
if !grpcutil.IsCompressorNameRegistered(c.Name()) {
|
||||
grpcutil.RegisteredCompressorNames = append(grpcutil.RegisteredCompressorNames, c.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// GetCompressor returns Compressor for the given compressor name.
|
||||
@@ -88,9 +85,9 @@ func GetCompressor(name string) Compressor {
|
||||
// methods can be called from concurrent goroutines.
|
||||
type Codec interface {
|
||||
// Marshal returns the wire format of v.
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
Marshal(v any) ([]byte, error)
|
||||
// Unmarshal parses the wire format into v.
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Unmarshal(data []byte, v any) error
|
||||
// Name returns the name of the Codec implementation. The returned string
|
||||
// will be used as part of content type in transmission. The result must be
|
||||
// static; the result cannot change between calls.
|
||||
|
4
vendor/google.golang.org/grpc/encoding/proto/proto.go
generated
vendored
4
vendor/google.golang.org/grpc/encoding/proto/proto.go
generated
vendored
@@ -37,7 +37,7 @@ func init() {
|
||||
// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
|
||||
type codec struct{}
|
||||
|
||||
func (codec) Marshal(v interface{}) ([]byte, error) {
|
||||
func (codec) Marshal(v any) ([]byte, error) {
|
||||
vv, ok := v.(proto.Message)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v)
|
||||
@@ -45,7 +45,7 @@ func (codec) Marshal(v interface{}) ([]byte, error) {
|
||||
return proto.Marshal(vv)
|
||||
}
|
||||
|
||||
func (codec) Unmarshal(data []byte, v interface{}) error {
|
||||
func (codec) Unmarshal(data []byte, v any) error {
|
||||
vv, ok := v.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v)
|
||||
|
40
vendor/google.golang.org/grpc/grpclog/component.go
generated
vendored
40
vendor/google.golang.org/grpc/grpclog/component.go
generated
vendored
@@ -31,71 +31,71 @@ type componentData struct {
|
||||
|
||||
var cache = map[string]*componentData{}
|
||||
|
||||
func (c *componentData) InfoDepth(depth int, args ...interface{}) {
|
||||
args = append([]interface{}{"[" + string(c.name) + "]"}, args...)
|
||||
func (c *componentData) InfoDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.InfoDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) WarningDepth(depth int, args ...interface{}) {
|
||||
args = append([]interface{}{"[" + string(c.name) + "]"}, args...)
|
||||
func (c *componentData) WarningDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.WarningDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) ErrorDepth(depth int, args ...interface{}) {
|
||||
args = append([]interface{}{"[" + string(c.name) + "]"}, args...)
|
||||
func (c *componentData) ErrorDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.ErrorDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) FatalDepth(depth int, args ...interface{}) {
|
||||
args = append([]interface{}{"[" + string(c.name) + "]"}, args...)
|
||||
func (c *componentData) FatalDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.FatalDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Info(args ...interface{}) {
|
||||
func (c *componentData) Info(args ...any) {
|
||||
c.InfoDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Warning(args ...interface{}) {
|
||||
func (c *componentData) Warning(args ...any) {
|
||||
c.WarningDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Error(args ...interface{}) {
|
||||
func (c *componentData) Error(args ...any) {
|
||||
c.ErrorDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Fatal(args ...interface{}) {
|
||||
func (c *componentData) Fatal(args ...any) {
|
||||
c.FatalDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Infof(format string, args ...interface{}) {
|
||||
func (c *componentData) Infof(format string, args ...any) {
|
||||
c.InfoDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Warningf(format string, args ...interface{}) {
|
||||
func (c *componentData) Warningf(format string, args ...any) {
|
||||
c.WarningDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Errorf(format string, args ...interface{}) {
|
||||
func (c *componentData) Errorf(format string, args ...any) {
|
||||
c.ErrorDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Fatalf(format string, args ...interface{}) {
|
||||
func (c *componentData) Fatalf(format string, args ...any) {
|
||||
c.FatalDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Infoln(args ...interface{}) {
|
||||
func (c *componentData) Infoln(args ...any) {
|
||||
c.InfoDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Warningln(args ...interface{}) {
|
||||
func (c *componentData) Warningln(args ...any) {
|
||||
c.WarningDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Errorln(args ...interface{}) {
|
||||
func (c *componentData) Errorln(args ...any) {
|
||||
c.ErrorDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Fatalln(args ...interface{}) {
|
||||
func (c *componentData) Fatalln(args ...any) {
|
||||
c.FatalDepth(1, args...)
|
||||
}
|
||||
|
||||
|
30
vendor/google.golang.org/grpc/grpclog/grpclog.go
generated
vendored
30
vendor/google.golang.org/grpc/grpclog/grpclog.go
generated
vendored
@@ -42,53 +42,53 @@ func V(l int) bool {
|
||||
}
|
||||
|
||||
// Info logs to the INFO log.
|
||||
func Info(args ...interface{}) {
|
||||
func Info(args ...any) {
|
||||
grpclog.Logger.Info(args...)
|
||||
}
|
||||
|
||||
// Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Infof(format string, args ...interface{}) {
|
||||
func Infof(format string, args ...any) {
|
||||
grpclog.Logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Infoln logs to the INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
func Infoln(args ...interface{}) {
|
||||
func Infoln(args ...any) {
|
||||
grpclog.Logger.Infoln(args...)
|
||||
}
|
||||
|
||||
// Warning logs to the WARNING log.
|
||||
func Warning(args ...interface{}) {
|
||||
func Warning(args ...any) {
|
||||
grpclog.Logger.Warning(args...)
|
||||
}
|
||||
|
||||
// Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Warningf(format string, args ...interface{}) {
|
||||
func Warningf(format string, args ...any) {
|
||||
grpclog.Logger.Warningf(format, args...)
|
||||
}
|
||||
|
||||
// Warningln logs to the WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
func Warningln(args ...interface{}) {
|
||||
func Warningln(args ...any) {
|
||||
grpclog.Logger.Warningln(args...)
|
||||
}
|
||||
|
||||
// Error logs to the ERROR log.
|
||||
func Error(args ...interface{}) {
|
||||
func Error(args ...any) {
|
||||
grpclog.Logger.Error(args...)
|
||||
}
|
||||
|
||||
// Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
func Errorf(format string, args ...any) {
|
||||
grpclog.Logger.Errorf(format, args...)
|
||||
}
|
||||
|
||||
// Errorln logs to the ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
func Errorln(args ...interface{}) {
|
||||
func Errorln(args ...any) {
|
||||
grpclog.Logger.Errorln(args...)
|
||||
}
|
||||
|
||||
// Fatal logs to the FATAL log. Arguments are handled in the manner of fmt.Print.
|
||||
// It calls os.Exit() with exit code 1.
|
||||
func Fatal(args ...interface{}) {
|
||||
func Fatal(args ...any) {
|
||||
grpclog.Logger.Fatal(args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
@@ -96,7 +96,7 @@ func Fatal(args ...interface{}) {
|
||||
|
||||
// Fatalf logs to the FATAL log. Arguments are handled in the manner of fmt.Printf.
|
||||
// It calls os.Exit() with exit code 1.
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
func Fatalf(format string, args ...any) {
|
||||
grpclog.Logger.Fatalf(format, args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
@@ -104,7 +104,7 @@ func Fatalf(format string, args ...interface{}) {
|
||||
|
||||
// Fatalln logs to the FATAL log. Arguments are handled in the manner of fmt.Println.
|
||||
// It calle os.Exit()) with exit code 1.
|
||||
func Fatalln(args ...interface{}) {
|
||||
func Fatalln(args ...any) {
|
||||
grpclog.Logger.Fatalln(args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
@@ -113,20 +113,20 @@ func Fatalln(args ...interface{}) {
|
||||
// Print prints to the logger. Arguments are handled in the manner of fmt.Print.
|
||||
//
|
||||
// Deprecated: use Info.
|
||||
func Print(args ...interface{}) {
|
||||
func Print(args ...any) {
|
||||
grpclog.Logger.Info(args...)
|
||||
}
|
||||
|
||||
// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf.
|
||||
//
|
||||
// Deprecated: use Infof.
|
||||
func Printf(format string, args ...interface{}) {
|
||||
func Printf(format string, args ...any) {
|
||||
grpclog.Logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Println prints to the logger. Arguments are handled in the manner of fmt.Println.
|
||||
//
|
||||
// Deprecated: use Infoln.
|
||||
func Println(args ...interface{}) {
|
||||
func Println(args ...any) {
|
||||
grpclog.Logger.Infoln(args...)
|
||||
}
|
||||
|
30
vendor/google.golang.org/grpc/grpclog/logger.go
generated
vendored
30
vendor/google.golang.org/grpc/grpclog/logger.go
generated
vendored
@@ -24,12 +24,12 @@ import "google.golang.org/grpc/internal/grpclog"
|
||||
//
|
||||
// Deprecated: use LoggerV2.
|
||||
type Logger interface {
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
Fatalln(args ...interface{})
|
||||
Print(args ...interface{})
|
||||
Printf(format string, args ...interface{})
|
||||
Println(args ...interface{})
|
||||
Fatal(args ...any)
|
||||
Fatalf(format string, args ...any)
|
||||
Fatalln(args ...any)
|
||||
Print(args ...any)
|
||||
Printf(format string, args ...any)
|
||||
Println(args ...any)
|
||||
}
|
||||
|
||||
// SetLogger sets the logger that is used in grpc. Call only from
|
||||
@@ -45,39 +45,39 @@ type loggerWrapper struct {
|
||||
Logger
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Info(args ...interface{}) {
|
||||
func (g *loggerWrapper) Info(args ...any) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Infoln(args ...interface{}) {
|
||||
func (g *loggerWrapper) Infoln(args ...any) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Infof(format string, args ...interface{}) {
|
||||
func (g *loggerWrapper) Infof(format string, args ...any) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warning(args ...interface{}) {
|
||||
func (g *loggerWrapper) Warning(args ...any) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warningln(args ...interface{}) {
|
||||
func (g *loggerWrapper) Warningln(args ...any) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warningf(format string, args ...interface{}) {
|
||||
func (g *loggerWrapper) Warningf(format string, args ...any) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Error(args ...interface{}) {
|
||||
func (g *loggerWrapper) Error(args ...any) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Errorln(args ...interface{}) {
|
||||
func (g *loggerWrapper) Errorln(args ...any) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Errorf(format string, args ...interface{}) {
|
||||
func (g *loggerWrapper) Errorf(format string, args ...any) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
|
63
vendor/google.golang.org/grpc/grpclog/loggerv2.go
generated
vendored
63
vendor/google.golang.org/grpc/grpclog/loggerv2.go
generated
vendored
@@ -22,7 +22,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -34,35 +33,35 @@ import (
|
||||
// LoggerV2 does underlying logging work for grpclog.
|
||||
type LoggerV2 interface {
|
||||
// Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
|
||||
Info(args ...interface{})
|
||||
Info(args ...any)
|
||||
// Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
Infoln(args ...interface{})
|
||||
Infoln(args ...any)
|
||||
// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
Infof(format string, args ...interface{})
|
||||
Infof(format string, args ...any)
|
||||
// Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
|
||||
Warning(args ...interface{})
|
||||
Warning(args ...any)
|
||||
// Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
Warningln(args ...interface{})
|
||||
Warningln(args ...any)
|
||||
// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
Warningf(format string, args ...interface{})
|
||||
Warningf(format string, args ...any)
|
||||
// Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
Error(args ...interface{})
|
||||
Error(args ...any)
|
||||
// Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
Errorln(args ...interface{})
|
||||
Errorln(args ...any)
|
||||
// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
Errorf(format string, args ...interface{})
|
||||
Errorf(format string, args ...any)
|
||||
// Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatal(args ...interface{})
|
||||
Fatal(args ...any)
|
||||
// Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalln(args ...interface{})
|
||||
Fatalln(args ...any)
|
||||
// Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalf(format string, args ...interface{})
|
||||
Fatalf(format string, args ...any)
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
V(l int) bool
|
||||
}
|
||||
@@ -140,9 +139,9 @@ func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config)
|
||||
// newLoggerV2 creates a loggerV2 to be used as default logger.
|
||||
// All logs are written to stderr.
|
||||
func newLoggerV2() LoggerV2 {
|
||||
errorW := ioutil.Discard
|
||||
warningW := ioutil.Discard
|
||||
infoW := ioutil.Discard
|
||||
errorW := io.Discard
|
||||
warningW := io.Discard
|
||||
infoW := io.Discard
|
||||
|
||||
logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
|
||||
switch logLevel {
|
||||
@@ -183,53 +182,53 @@ func (g *loggerT) output(severity int, s string) {
|
||||
g.m[severity].Output(2, string(b))
|
||||
}
|
||||
|
||||
func (g *loggerT) Info(args ...interface{}) {
|
||||
func (g *loggerT) Info(args ...any) {
|
||||
g.output(infoLog, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Infoln(args ...interface{}) {
|
||||
func (g *loggerT) Infoln(args ...any) {
|
||||
g.output(infoLog, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Infof(format string, args ...interface{}) {
|
||||
func (g *loggerT) Infof(format string, args ...any) {
|
||||
g.output(infoLog, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Warning(args ...interface{}) {
|
||||
func (g *loggerT) Warning(args ...any) {
|
||||
g.output(warningLog, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Warningln(args ...interface{}) {
|
||||
func (g *loggerT) Warningln(args ...any) {
|
||||
g.output(warningLog, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Warningf(format string, args ...interface{}) {
|
||||
func (g *loggerT) Warningf(format string, args ...any) {
|
||||
g.output(warningLog, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Error(args ...interface{}) {
|
||||
func (g *loggerT) Error(args ...any) {
|
||||
g.output(errorLog, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Errorln(args ...interface{}) {
|
||||
func (g *loggerT) Errorln(args ...any) {
|
||||
g.output(errorLog, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Errorf(format string, args ...interface{}) {
|
||||
func (g *loggerT) Errorf(format string, args ...any) {
|
||||
g.output(errorLog, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatal(args ...interface{}) {
|
||||
func (g *loggerT) Fatal(args ...any) {
|
||||
g.output(fatalLog, fmt.Sprint(args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatalln(args ...interface{}) {
|
||||
func (g *loggerT) Fatalln(args ...any) {
|
||||
g.output(fatalLog, fmt.Sprintln(args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatalf(format string, args ...interface{}) {
|
||||
func (g *loggerT) Fatalf(format string, args ...any) {
|
||||
g.output(fatalLog, fmt.Sprintf(format, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -249,11 +248,11 @@ func (g *loggerT) V(l int) bool {
|
||||
type DepthLoggerV2 interface {
|
||||
LoggerV2
|
||||
// InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
InfoDepth(depth int, args ...interface{})
|
||||
InfoDepth(depth int, args ...any)
|
||||
// WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
WarningDepth(depth int, args ...interface{})
|
||||
WarningDepth(depth int, args ...any)
|
||||
// ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
ErrorDepth(depth int, args ...interface{})
|
||||
ErrorDepth(depth int, args ...any)
|
||||
// FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
FatalDepth(depth int, args ...interface{})
|
||||
FatalDepth(depth int, args ...any)
|
||||
}
|
||||
|
308
vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
generated
vendored
Normal file
308
vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
// Copyright 2015 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.22.0
|
||||
// source: grpc/health/v1/health.proto
|
||||
|
||||
package grpc_health_v1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type HealthCheckResponse_ServingStatus int32
|
||||
|
||||
const (
|
||||
HealthCheckResponse_UNKNOWN HealthCheckResponse_ServingStatus = 0
|
||||
HealthCheckResponse_SERVING HealthCheckResponse_ServingStatus = 1
|
||||
HealthCheckResponse_NOT_SERVING HealthCheckResponse_ServingStatus = 2
|
||||
HealthCheckResponse_SERVICE_UNKNOWN HealthCheckResponse_ServingStatus = 3 // Used only by the Watch method.
|
||||
)
|
||||
|
||||
// Enum value maps for HealthCheckResponse_ServingStatus.
|
||||
var (
|
||||
HealthCheckResponse_ServingStatus_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "SERVING",
|
||||
2: "NOT_SERVING",
|
||||
3: "SERVICE_UNKNOWN",
|
||||
}
|
||||
HealthCheckResponse_ServingStatus_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"SERVING": 1,
|
||||
"NOT_SERVING": 2,
|
||||
"SERVICE_UNKNOWN": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x HealthCheckResponse_ServingStatus) Enum() *HealthCheckResponse_ServingStatus {
|
||||
p := new(HealthCheckResponse_ServingStatus)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x HealthCheckResponse_ServingStatus) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (HealthCheckResponse_ServingStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_grpc_health_v1_health_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (HealthCheckResponse_ServingStatus) Type() protoreflect.EnumType {
|
||||
return &file_grpc_health_v1_health_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x HealthCheckResponse_ServingStatus) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use HealthCheckResponse_ServingStatus.Descriptor instead.
|
||||
func (HealthCheckResponse_ServingStatus) EnumDescriptor() ([]byte, []int) {
|
||||
return file_grpc_health_v1_health_proto_rawDescGZIP(), []int{1, 0}
|
||||
}
|
||||
|
||||
type HealthCheckRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
||||
}
|
||||
|
||||
func (x *HealthCheckRequest) Reset() {
|
||||
*x = HealthCheckRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_health_v1_health_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *HealthCheckRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*HealthCheckRequest) ProtoMessage() {}
|
||||
|
||||
func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_health_v1_health_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead.
|
||||
func (*HealthCheckRequest) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_health_v1_health_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *HealthCheckRequest) GetService() string {
|
||||
if x != nil {
|
||||
return x.Service
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type HealthCheckResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,proto3,enum=grpc.health.v1.HealthCheckResponse_ServingStatus" json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (x *HealthCheckResponse) Reset() {
|
||||
*x = HealthCheckResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_health_v1_health_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *HealthCheckResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*HealthCheckResponse) ProtoMessage() {}
|
||||
|
||||
func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_health_v1_health_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead.
|
||||
func (*HealthCheckResponse) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_health_v1_health_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *HealthCheckResponse) GetStatus() HealthCheckResponse_ServingStatus {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return HealthCheckResponse_UNKNOWN
|
||||
}
|
||||
|
||||
var File_grpc_health_v1_health_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_grpc_health_v1_health_proto_rawDesc = []byte{
|
||||
0x0a, 0x1b, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x22, 0x2e, 0x0a,
|
||||
0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0xb1, 0x01,
|
||||
0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65,
|
||||
0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x22, 0x4f, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b,
|
||||
0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e,
|
||||
0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f,
|
||||
0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
|
||||
0x03, 0x32, 0xae, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x50, 0x0a, 0x05,
|
||||
0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65,
|
||||
0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74,
|
||||
0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52,
|
||||
0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x22, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68,
|
||||
0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x30, 0x01, 0x42, 0x61, 0x0a, 0x11, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65,
|
||||
0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67,
|
||||
0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x68,
|
||||
0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74,
|
||||
0x68, 0x5f, 0x76, 0x31, 0xaa, 0x02, 0x0e, 0x47, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x65, 0x61, 0x6c,
|
||||
0x74, 0x68, 0x2e, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_grpc_health_v1_health_proto_rawDescOnce sync.Once
|
||||
file_grpc_health_v1_health_proto_rawDescData = file_grpc_health_v1_health_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_grpc_health_v1_health_proto_rawDescGZIP() []byte {
|
||||
file_grpc_health_v1_health_proto_rawDescOnce.Do(func() {
|
||||
file_grpc_health_v1_health_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_health_v1_health_proto_rawDescData)
|
||||
})
|
||||
return file_grpc_health_v1_health_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_grpc_health_v1_health_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_grpc_health_v1_health_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_grpc_health_v1_health_proto_goTypes = []interface{}{
|
||||
(HealthCheckResponse_ServingStatus)(0), // 0: grpc.health.v1.HealthCheckResponse.ServingStatus
|
||||
(*HealthCheckRequest)(nil), // 1: grpc.health.v1.HealthCheckRequest
|
||||
(*HealthCheckResponse)(nil), // 2: grpc.health.v1.HealthCheckResponse
|
||||
}
|
||||
var file_grpc_health_v1_health_proto_depIdxs = []int32{
|
||||
0, // 0: grpc.health.v1.HealthCheckResponse.status:type_name -> grpc.health.v1.HealthCheckResponse.ServingStatus
|
||||
1, // 1: grpc.health.v1.Health.Check:input_type -> grpc.health.v1.HealthCheckRequest
|
||||
1, // 2: grpc.health.v1.Health.Watch:input_type -> grpc.health.v1.HealthCheckRequest
|
||||
2, // 3: grpc.health.v1.Health.Check:output_type -> grpc.health.v1.HealthCheckResponse
|
||||
2, // 4: grpc.health.v1.Health.Watch:output_type -> grpc.health.v1.HealthCheckResponse
|
||||
3, // [3:5] is the sub-list for method output_type
|
||||
1, // [1:3] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_grpc_health_v1_health_proto_init() }
|
||||
func file_grpc_health_v1_health_proto_init() {
|
||||
if File_grpc_health_v1_health_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_grpc_health_v1_health_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HealthCheckRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_health_v1_health_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HealthCheckResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_grpc_health_v1_health_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_grpc_health_v1_health_proto_goTypes,
|
||||
DependencyIndexes: file_grpc_health_v1_health_proto_depIdxs,
|
||||
EnumInfos: file_grpc_health_v1_health_proto_enumTypes,
|
||||
MessageInfos: file_grpc_health_v1_health_proto_msgTypes,
|
||||
}.Build()
|
||||
File_grpc_health_v1_health_proto = out.File
|
||||
file_grpc_health_v1_health_proto_rawDesc = nil
|
||||
file_grpc_health_v1_health_proto_goTypes = nil
|
||||
file_grpc_health_v1_health_proto_depIdxs = nil
|
||||
}
|
237
vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
generated
vendored
Normal file
237
vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright 2015 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.22.0
|
||||
// source: grpc/health/v1/health.proto
|
||||
|
||||
package grpc_health_v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
Health_Check_FullMethodName = "/grpc.health.v1.Health/Check"
|
||||
Health_Watch_FullMethodName = "/grpc.health.v1.Health/Watch"
|
||||
)
|
||||
|
||||
// HealthClient is the client API for Health service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type HealthClient interface {
|
||||
// Check gets the health of the specified service. If the requested service
|
||||
// is unknown, the call will fail with status NOT_FOUND. If the caller does
|
||||
// not specify a service name, the server should respond with its overall
|
||||
// health status.
|
||||
//
|
||||
// Clients should set a deadline when calling Check, and can declare the
|
||||
// server unhealthy if they do not receive a timely response.
|
||||
//
|
||||
// Check implementations should be idempotent and side effect free.
|
||||
Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
|
||||
// Performs a watch for the serving status of the requested service.
|
||||
// The server will immediately send back a message indicating the current
|
||||
// serving status. It will then subsequently send a new message whenever
|
||||
// the service's serving status changes.
|
||||
//
|
||||
// If the requested service is unknown when the call is received, the
|
||||
// server will send a message setting the serving status to
|
||||
// SERVICE_UNKNOWN but will *not* terminate the call. If at some
|
||||
// future point, the serving status of the service becomes known, the
|
||||
// server will send a new message with the service's serving status.
|
||||
//
|
||||
// If the call terminates with status UNIMPLEMENTED, then clients
|
||||
// should assume this method is not supported and should not retry the
|
||||
// call. If the call terminates with any other status (including OK),
|
||||
// clients should retry the call with appropriate exponential backoff.
|
||||
Watch(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (Health_WatchClient, error)
|
||||
}
|
||||
|
||||
type healthClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewHealthClient(cc grpc.ClientConnInterface) HealthClient {
|
||||
return &healthClient{cc}
|
||||
}
|
||||
|
||||
func (c *healthClient) Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
|
||||
out := new(HealthCheckResponse)
|
||||
err := c.cc.Invoke(ctx, Health_Check_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *healthClient) Watch(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (Health_WatchClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Health_ServiceDesc.Streams[0], Health_Watch_FullMethodName, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &healthWatchClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Health_WatchClient interface {
|
||||
Recv() (*HealthCheckResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type healthWatchClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *healthWatchClient) Recv() (*HealthCheckResponse, error) {
|
||||
m := new(HealthCheckResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// HealthServer is the server API for Health service.
|
||||
// All implementations should embed UnimplementedHealthServer
|
||||
// for forward compatibility
|
||||
type HealthServer interface {
|
||||
// Check gets the health of the specified service. If the requested service
|
||||
// is unknown, the call will fail with status NOT_FOUND. If the caller does
|
||||
// not specify a service name, the server should respond with its overall
|
||||
// health status.
|
||||
//
|
||||
// Clients should set a deadline when calling Check, and can declare the
|
||||
// server unhealthy if they do not receive a timely response.
|
||||
//
|
||||
// Check implementations should be idempotent and side effect free.
|
||||
Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
|
||||
// Performs a watch for the serving status of the requested service.
|
||||
// The server will immediately send back a message indicating the current
|
||||
// serving status. It will then subsequently send a new message whenever
|
||||
// the service's serving status changes.
|
||||
//
|
||||
// If the requested service is unknown when the call is received, the
|
||||
// server will send a message setting the serving status to
|
||||
// SERVICE_UNKNOWN but will *not* terminate the call. If at some
|
||||
// future point, the serving status of the service becomes known, the
|
||||
// server will send a new message with the service's serving status.
|
||||
//
|
||||
// If the call terminates with status UNIMPLEMENTED, then clients
|
||||
// should assume this method is not supported and should not retry the
|
||||
// call. If the call terminates with any other status (including OK),
|
||||
// clients should retry the call with appropriate exponential backoff.
|
||||
Watch(*HealthCheckRequest, Health_WatchServer) error
|
||||
}
|
||||
|
||||
// UnimplementedHealthServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedHealthServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedHealthServer) Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Check not implemented")
|
||||
}
|
||||
func (UnimplementedHealthServer) Watch(*HealthCheckRequest, Health_WatchServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Watch not implemented")
|
||||
}
|
||||
|
||||
// UnsafeHealthServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to HealthServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeHealthServer interface {
|
||||
mustEmbedUnimplementedHealthServer()
|
||||
}
|
||||
|
||||
func RegisterHealthServer(s grpc.ServiceRegistrar, srv HealthServer) {
|
||||
s.RegisterService(&Health_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Health_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(HealthCheckRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HealthServer).Check(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Health_Check_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HealthServer).Check(ctx, req.(*HealthCheckRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Health_Watch_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(HealthCheckRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(HealthServer).Watch(m, &healthWatchServer{stream})
|
||||
}
|
||||
|
||||
type Health_WatchServer interface {
|
||||
Send(*HealthCheckResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type healthWatchServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *healthWatchServer) Send(m *HealthCheckResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
// Health_ServiceDesc is the grpc.ServiceDesc for Health service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Health_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "grpc.health.v1.Health",
|
||||
HandlerType: (*HealthServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Check",
|
||||
Handler: _Health_Check_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Watch",
|
||||
Handler: _Health_Watch_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "grpc/health/v1/health.proto",
|
||||
}
|
12
vendor/google.golang.org/grpc/interceptor.go
generated
vendored
12
vendor/google.golang.org/grpc/interceptor.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
|
||||
type UnaryInvoker func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error
|
||||
type UnaryInvoker func(ctx context.Context, method string, req, reply any, cc *ClientConn, opts ...CallOption) error
|
||||
|
||||
// UnaryClientInterceptor intercepts the execution of a unary RPC on the client.
|
||||
// Unary interceptors can be specified as a DialOption, using
|
||||
@@ -40,7 +40,7 @@ type UnaryInvoker func(ctx context.Context, method string, req, reply interface{
|
||||
// defaults from the ClientConn as well as per-call options.
|
||||
//
|
||||
// The returned error must be compatible with the status package.
|
||||
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
|
||||
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply any, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
|
||||
|
||||
// Streamer is called by StreamClientInterceptor to create a ClientStream.
|
||||
type Streamer func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error)
|
||||
@@ -66,7 +66,7 @@ type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *Cli
|
||||
// server side. All per-rpc information may be mutated by the interceptor.
|
||||
type UnaryServerInfo struct {
|
||||
// Server is the service implementation the user provides. This is read-only.
|
||||
Server interface{}
|
||||
Server any
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
}
|
||||
@@ -78,13 +78,13 @@ type UnaryServerInfo struct {
|
||||
// status package, or be one of the context errors. Otherwise, gRPC will use
|
||||
// codes.Unknown as the status code and err.Error() as the status message of the
|
||||
// RPC.
|
||||
type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
|
||||
type UnaryHandler func(ctx context.Context, req any) (any, error)
|
||||
|
||||
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
|
||||
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
|
||||
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
|
||||
// to complete the RPC.
|
||||
type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)
|
||||
type UnaryServerInterceptor func(ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler) (resp any, err error)
|
||||
|
||||
// StreamServerInfo consists of various information about a streaming RPC on
|
||||
// server side. All per-rpc information may be mutated by the interceptor.
|
||||
@@ -101,4 +101,4 @@ type StreamServerInfo struct {
|
||||
// info contains all the information of this RPC the interceptor can operate on. And handler is the
|
||||
// service method implementation. It is the responsibility of the interceptor to invoke handler to
|
||||
// complete the RPC.
|
||||
type StreamServerInterceptor func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error
|
||||
type StreamServerInterceptor func(srv any, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error
|
||||
|
36
vendor/google.golang.org/grpc/internal/backoff/backoff.go
generated
vendored
36
vendor/google.golang.org/grpc/internal/backoff/backoff.go
generated
vendored
@@ -23,6 +23,8 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
grpcbackoff "google.golang.org/grpc/backoff"
|
||||
@@ -71,3 +73,37 @@ func (bc Exponential) Backoff(retries int) time.Duration {
|
||||
}
|
||||
return time.Duration(backoff)
|
||||
}
|
||||
|
||||
// ErrResetBackoff is the error to be returned by the function executed by RunF,
|
||||
// to instruct the latter to reset its backoff state.
|
||||
var ErrResetBackoff = errors.New("reset backoff state")
|
||||
|
||||
// RunF provides a convenient way to run a function f repeatedly until the
|
||||
// context expires or f returns a non-nil error that is not ErrResetBackoff.
|
||||
// When f returns ErrResetBackoff, RunF continues to run f, but resets its
|
||||
// backoff state before doing so. backoff accepts an integer representing the
|
||||
// number of retries, and returns the amount of time to backoff.
|
||||
func RunF(ctx context.Context, f func() error, backoff func(int) time.Duration) {
|
||||
attempt := 0
|
||||
timer := time.NewTimer(0)
|
||||
for ctx.Err() == nil {
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
}
|
||||
|
||||
err := f()
|
||||
if errors.Is(err, ErrResetBackoff) {
|
||||
timer.Reset(0)
|
||||
attempt = 0
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
timer.Reset(backoff(attempt))
|
||||
attempt++
|
||||
}
|
||||
}
|
||||
|
59
vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
generated
vendored
59
vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
generated
vendored
@@ -200,8 +200,8 @@ func (gsb *Balancer) ExitIdle() {
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateSubConnState forwards the update to the appropriate child.
|
||||
func (gsb *Balancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
// updateSubConnState forwards the update to the appropriate child.
|
||||
func (gsb *Balancer) updateSubConnState(sc balancer.SubConn, state balancer.SubConnState, cb func(balancer.SubConnState)) {
|
||||
gsb.currentMu.Lock()
|
||||
defer gsb.currentMu.Unlock()
|
||||
gsb.mu.Lock()
|
||||
@@ -214,13 +214,26 @@ func (gsb *Balancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubC
|
||||
} else if gsb.balancerPending != nil && gsb.balancerPending.subconns[sc] {
|
||||
balToUpdate = gsb.balancerPending
|
||||
}
|
||||
gsb.mu.Unlock()
|
||||
if balToUpdate == nil {
|
||||
// SubConn belonged to a stale lb policy that has not yet fully closed,
|
||||
// or the balancer was already closed.
|
||||
gsb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
balToUpdate.UpdateSubConnState(sc, state)
|
||||
if state.ConnectivityState == connectivity.Shutdown {
|
||||
delete(balToUpdate.subconns, sc)
|
||||
}
|
||||
gsb.mu.Unlock()
|
||||
if cb != nil {
|
||||
cb(state)
|
||||
} else {
|
||||
balToUpdate.UpdateSubConnState(sc, state)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateSubConnState forwards the update to the appropriate child.
|
||||
func (gsb *Balancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
gsb.updateSubConnState(sc, state, nil)
|
||||
}
|
||||
|
||||
// Close closes any active child balancers.
|
||||
@@ -242,7 +255,7 @@ func (gsb *Balancer) Close() {
|
||||
//
|
||||
// It implements the balancer.ClientConn interface and is passed down in that
|
||||
// capacity to the wrapped balancer. It maintains a set of subConns created by
|
||||
// the wrapped balancer and calls from the latter to create/update/remove
|
||||
// the wrapped balancer and calls from the latter to create/update/shutdown
|
||||
// SubConns update this set before being forwarded to the parent ClientConn.
|
||||
// State updates from the wrapped balancer can result in invocation of the
|
||||
// graceful switch logic.
|
||||
@@ -254,21 +267,10 @@ type balancerWrapper struct {
|
||||
subconns map[balancer.SubConn]bool // subconns created by this balancer
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
if state.ConnectivityState == connectivity.Shutdown {
|
||||
bw.gsb.mu.Lock()
|
||||
delete(bw.subconns, sc)
|
||||
bw.gsb.mu.Unlock()
|
||||
}
|
||||
// There is no need to protect this read with a mutex, as the write to the
|
||||
// Balancer field happens in SwitchTo, which completes before this can be
|
||||
// called.
|
||||
bw.Balancer.UpdateSubConnState(sc, state)
|
||||
}
|
||||
|
||||
// Close closes the underlying LB policy and removes the subconns it created. bw
|
||||
// must not be referenced via balancerCurrent or balancerPending in gsb when
|
||||
// called. gsb.mu must not be held. Does not panic with a nil receiver.
|
||||
// Close closes the underlying LB policy and shuts down the subconns it
|
||||
// created. bw must not be referenced via balancerCurrent or balancerPending in
|
||||
// gsb when called. gsb.mu must not be held. Does not panic with a nil
|
||||
// receiver.
|
||||
func (bw *balancerWrapper) Close() {
|
||||
// before Close is called.
|
||||
if bw == nil {
|
||||
@@ -281,7 +283,7 @@ func (bw *balancerWrapper) Close() {
|
||||
bw.Balancer.Close()
|
||||
bw.gsb.mu.Lock()
|
||||
for sc := range bw.subconns {
|
||||
bw.gsb.cc.RemoveSubConn(sc)
|
||||
sc.Shutdown()
|
||||
}
|
||||
bw.gsb.mu.Unlock()
|
||||
}
|
||||
@@ -335,13 +337,16 @@ func (bw *balancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.Ne
|
||||
}
|
||||
bw.gsb.mu.Unlock()
|
||||
|
||||
var sc balancer.SubConn
|
||||
oldListener := opts.StateListener
|
||||
opts.StateListener = func(state balancer.SubConnState) { bw.gsb.updateSubConnState(sc, state, oldListener) }
|
||||
sc, err := bw.gsb.cc.NewSubConn(addrs, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bw.gsb.mu.Lock()
|
||||
if !bw.gsb.balancerCurrentOrPending(bw) { // balancer was closed during this call
|
||||
bw.gsb.cc.RemoveSubConn(sc)
|
||||
sc.Shutdown()
|
||||
bw.gsb.mu.Unlock()
|
||||
return nil, fmt.Errorf("%T at address %p that called NewSubConn is deleted", bw, bw)
|
||||
}
|
||||
@@ -360,13 +365,9 @@ func (bw *balancerWrapper) ResolveNow(opts resolver.ResolveNowOptions) {
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||
bw.gsb.mu.Lock()
|
||||
if !bw.gsb.balancerCurrentOrPending(bw) {
|
||||
bw.gsb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
bw.gsb.mu.Unlock()
|
||||
bw.gsb.cc.RemoveSubConn(sc)
|
||||
// Note: existing third party balancers may call this, so it must remain
|
||||
// until RemoveSubConn is fully removed.
|
||||
sc.Shutdown()
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||
|
4
vendor/google.golang.org/grpc/internal/balancerload/load.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/balancerload/load.go
generated
vendored
@@ -25,7 +25,7 @@ import (
|
||||
// Parser converts loads from metadata into a concrete type.
|
||||
type Parser interface {
|
||||
// Parse parses loads from metadata.
|
||||
Parse(md metadata.MD) interface{}
|
||||
Parse(md metadata.MD) any
|
||||
}
|
||||
|
||||
var parser Parser
|
||||
@@ -38,7 +38,7 @@ func SetParser(lr Parser) {
|
||||
}
|
||||
|
||||
// Parse calls parser.Read().
|
||||
func Parse(md metadata.MD) interface{} {
|
||||
func Parse(md metadata.MD) any {
|
||||
if parser == nil {
|
||||
return nil
|
||||
}
|
||||
|
11
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
11
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
@@ -28,8 +28,13 @@ import (
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
)
|
||||
|
||||
// Logger is the global binary logger. It can be used to get binary logger for
|
||||
// each method.
|
||||
var grpclogLogger = grpclog.Component("binarylog")
|
||||
|
||||
// Logger specifies MethodLoggers for method names with a Log call that
|
||||
// takes a context.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
type Logger interface {
|
||||
GetMethodLogger(methodName string) MethodLogger
|
||||
}
|
||||
@@ -40,8 +45,6 @@ type Logger interface {
|
||||
// It is used to get a MethodLogger for each individual method.
|
||||
var binLogger Logger
|
||||
|
||||
var grpclogLogger = grpclog.Component("binarylog")
|
||||
|
||||
// SetLogger sets the binary logger.
|
||||
//
|
||||
// Only call this at init time.
|
||||
|
146
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
146
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
@@ -19,6 +19,7 @@
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@@ -26,7 +27,7 @@ import (
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -48,8 +49,11 @@ func (g *callIDGenerator) reset() {
|
||||
var idGen callIDGenerator
|
||||
|
||||
// MethodLogger is the sub-logger for each method.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
type MethodLogger interface {
|
||||
Log(LogEntryConfig)
|
||||
Log(context.Context, LogEntryConfig)
|
||||
}
|
||||
|
||||
// TruncatingMethodLogger is a method logger that truncates headers and messages
|
||||
@@ -64,6 +68,9 @@ type TruncatingMethodLogger struct {
|
||||
}
|
||||
|
||||
// NewTruncatingMethodLogger returns a new truncating method logger.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger {
|
||||
return &TruncatingMethodLogger{
|
||||
headerMaxLen: h,
|
||||
@@ -79,7 +86,7 @@ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger {
|
||||
// Build is an internal only method for building the proto message out of the
|
||||
// input event. It's made public to enable other library to reuse as much logic
|
||||
// in TruncatingMethodLogger as possible.
|
||||
func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
|
||||
func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry {
|
||||
m := c.toProto()
|
||||
timestamp, _ := ptypes.TimestampProto(time.Now())
|
||||
m.Timestamp = timestamp
|
||||
@@ -87,22 +94,22 @@ func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
|
||||
m.SequenceIdWithinCall = ml.idWithinCallGen.next()
|
||||
|
||||
switch pay := m.Payload.(type) {
|
||||
case *pb.GrpcLogEntry_ClientHeader:
|
||||
case *binlogpb.GrpcLogEntry_ClientHeader:
|
||||
m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata())
|
||||
case *pb.GrpcLogEntry_ServerHeader:
|
||||
case *binlogpb.GrpcLogEntry_ServerHeader:
|
||||
m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata())
|
||||
case *pb.GrpcLogEntry_Message:
|
||||
case *binlogpb.GrpcLogEntry_Message:
|
||||
m.PayloadTruncated = ml.truncateMessage(pay.Message)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Log creates a proto binary log entry, and logs it to the sink.
|
||||
func (ml *TruncatingMethodLogger) Log(c LogEntryConfig) {
|
||||
func (ml *TruncatingMethodLogger) Log(ctx context.Context, c LogEntryConfig) {
|
||||
ml.sink.Write(ml.Build(c))
|
||||
}
|
||||
|
||||
func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
|
||||
func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *binlogpb.Metadata) (truncated bool) {
|
||||
if ml.headerMaxLen == maxUInt {
|
||||
return false
|
||||
}
|
||||
@@ -121,7 +128,7 @@ func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated
|
||||
// but not counted towards the size limit.
|
||||
continue
|
||||
}
|
||||
currentEntryLen := uint64(len(entry.Value))
|
||||
currentEntryLen := uint64(len(entry.GetKey())) + uint64(len(entry.GetValue()))
|
||||
if currentEntryLen > bytesLimit {
|
||||
break
|
||||
}
|
||||
@@ -132,7 +139,7 @@ func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated
|
||||
return truncated
|
||||
}
|
||||
|
||||
func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
|
||||
func (ml *TruncatingMethodLogger) truncateMessage(msgPb *binlogpb.Message) (truncated bool) {
|
||||
if ml.messageMaxLen == maxUInt {
|
||||
return false
|
||||
}
|
||||
@@ -144,8 +151,11 @@ func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated
|
||||
}
|
||||
|
||||
// LogEntryConfig represents the configuration for binary log entry.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
type LogEntryConfig interface {
|
||||
toProto() *pb.GrpcLogEntry
|
||||
toProto() *binlogpb.GrpcLogEntry
|
||||
}
|
||||
|
||||
// ClientHeader configs the binary log entry to be a ClientHeader entry.
|
||||
@@ -159,10 +169,10 @@ type ClientHeader struct {
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ClientHeader) toProto() *pb.GrpcLogEntry {
|
||||
func (c *ClientHeader) toProto() *binlogpb.GrpcLogEntry {
|
||||
// This function doesn't need to set all the fields (e.g. seq ID). The Log
|
||||
// function will set the fields when necessary.
|
||||
clientHeader := &pb.ClientHeader{
|
||||
clientHeader := &binlogpb.ClientHeader{
|
||||
Metadata: mdToMetadataProto(c.Header),
|
||||
MethodName: c.MethodName,
|
||||
Authority: c.Authority,
|
||||
@@ -170,16 +180,16 @@ func (c *ClientHeader) toProto() *pb.GrpcLogEntry {
|
||||
if c.Timeout > 0 {
|
||||
clientHeader.Timeout = ptypes.DurationProto(c.Timeout)
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
|
||||
Payload: &pb.GrpcLogEntry_ClientHeader{
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
|
||||
Payload: &binlogpb.GrpcLogEntry_ClientHeader{
|
||||
ClientHeader: clientHeader,
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
@@ -195,19 +205,19 @@ type ServerHeader struct {
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ServerHeader) toProto() *pb.GrpcLogEntry {
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
|
||||
Payload: &pb.GrpcLogEntry_ServerHeader{
|
||||
ServerHeader: &pb.ServerHeader{
|
||||
func (c *ServerHeader) toProto() *binlogpb.GrpcLogEntry {
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
|
||||
Payload: &binlogpb.GrpcLogEntry_ServerHeader{
|
||||
ServerHeader: &binlogpb.ServerHeader{
|
||||
Metadata: mdToMetadataProto(c.Header),
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
@@ -220,10 +230,10 @@ type ClientMessage struct {
|
||||
OnClientSide bool
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message interface{}
|
||||
Message any
|
||||
}
|
||||
|
||||
func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
|
||||
func (c *ClientMessage) toProto() *binlogpb.GrpcLogEntry {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
@@ -238,19 +248,19 @@ func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
|
||||
} else {
|
||||
grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte")
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
|
||||
Payload: &pb.GrpcLogEntry_Message{
|
||||
Message: &pb.Message{
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
|
||||
Payload: &binlogpb.GrpcLogEntry_Message{
|
||||
Message: &binlogpb.Message{
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -260,10 +270,10 @@ type ServerMessage struct {
|
||||
OnClientSide bool
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message interface{}
|
||||
Message any
|
||||
}
|
||||
|
||||
func (c *ServerMessage) toProto() *pb.GrpcLogEntry {
|
||||
func (c *ServerMessage) toProto() *binlogpb.GrpcLogEntry {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
@@ -278,19 +288,19 @@ func (c *ServerMessage) toProto() *pb.GrpcLogEntry {
|
||||
} else {
|
||||
grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte")
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
|
||||
Payload: &pb.GrpcLogEntry_Message{
|
||||
Message: &pb.Message{
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
|
||||
Payload: &binlogpb.GrpcLogEntry_Message{
|
||||
Message: &binlogpb.Message{
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -300,15 +310,15 @@ type ClientHalfClose struct {
|
||||
OnClientSide bool
|
||||
}
|
||||
|
||||
func (c *ClientHalfClose) toProto() *pb.GrpcLogEntry {
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
|
||||
func (c *ClientHalfClose) toProto() *binlogpb.GrpcLogEntry {
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
|
||||
Payload: nil, // No payload here.
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -324,7 +334,7 @@ type ServerTrailer struct {
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
|
||||
func (c *ServerTrailer) toProto() *binlogpb.GrpcLogEntry {
|
||||
st, ok := status.FromError(c.Err)
|
||||
if !ok {
|
||||
grpclogLogger.Info("binarylogging: error in trailer is not a status error")
|
||||
@@ -340,10 +350,10 @@ func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
|
||||
grpclogLogger.Infof("binarylogging: failed to marshal status proto: %v", err)
|
||||
}
|
||||
}
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
|
||||
Payload: &pb.GrpcLogEntry_Trailer{
|
||||
Trailer: &pb.Trailer{
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
|
||||
Payload: &binlogpb.GrpcLogEntry_Trailer{
|
||||
Trailer: &binlogpb.Trailer{
|
||||
Metadata: mdToMetadataProto(c.Trailer),
|
||||
StatusCode: uint32(st.Code()),
|
||||
StatusMessage: st.Message(),
|
||||
@@ -352,9 +362,9 @@ func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
@@ -367,15 +377,15 @@ type Cancel struct {
|
||||
OnClientSide bool
|
||||
}
|
||||
|
||||
func (c *Cancel) toProto() *pb.GrpcLogEntry {
|
||||
ret := &pb.GrpcLogEntry{
|
||||
Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL,
|
||||
func (c *Cancel) toProto() *binlogpb.GrpcLogEntry {
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CANCEL,
|
||||
Payload: nil,
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -392,15 +402,15 @@ func metadataKeyOmit(key string) bool {
|
||||
return strings.HasPrefix(key, "grpc-")
|
||||
}
|
||||
|
||||
func mdToMetadataProto(md metadata.MD) *pb.Metadata {
|
||||
ret := &pb.Metadata{}
|
||||
func mdToMetadataProto(md metadata.MD) *binlogpb.Metadata {
|
||||
ret := &binlogpb.Metadata{}
|
||||
for k, vv := range md {
|
||||
if metadataKeyOmit(k) {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
ret.Entry = append(ret.Entry,
|
||||
&pb.MetadataEntry{
|
||||
&binlogpb.MetadataEntry{
|
||||
Key: k,
|
||||
Value: []byte(v),
|
||||
},
|
||||
@@ -410,26 +420,26 @@ func mdToMetadataProto(md metadata.MD) *pb.Metadata {
|
||||
return ret
|
||||
}
|
||||
|
||||
func addrToProto(addr net.Addr) *pb.Address {
|
||||
ret := &pb.Address{}
|
||||
func addrToProto(addr net.Addr) *binlogpb.Address {
|
||||
ret := &binlogpb.Address{}
|
||||
switch a := addr.(type) {
|
||||
case *net.TCPAddr:
|
||||
if a.IP.To4() != nil {
|
||||
ret.Type = pb.Address_TYPE_IPV4
|
||||
ret.Type = binlogpb.Address_TYPE_IPV4
|
||||
} else if a.IP.To16() != nil {
|
||||
ret.Type = pb.Address_TYPE_IPV6
|
||||
ret.Type = binlogpb.Address_TYPE_IPV6
|
||||
} else {
|
||||
ret.Type = pb.Address_TYPE_UNKNOWN
|
||||
ret.Type = binlogpb.Address_TYPE_UNKNOWN
|
||||
// Do not set address and port fields.
|
||||
break
|
||||
}
|
||||
ret.Address = a.IP.String()
|
||||
ret.IpPort = uint32(a.Port)
|
||||
case *net.UnixAddr:
|
||||
ret.Type = pb.Address_TYPE_UNIX
|
||||
ret.Type = binlogpb.Address_TYPE_UNIX
|
||||
ret.Address = a.String()
|
||||
default:
|
||||
ret.Type = pb.Address_TYPE_UNKNOWN
|
||||
ret.Type = binlogpb.Address_TYPE_UNKNOWN
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
12
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
12
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
@@ -26,7 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -42,15 +42,15 @@ type Sink interface {
|
||||
// Write will be called to write the log entry into the sink.
|
||||
//
|
||||
// It should be thread-safe so it can be called in parallel.
|
||||
Write(*pb.GrpcLogEntry) error
|
||||
Write(*binlogpb.GrpcLogEntry) error
|
||||
// Close will be called when the Sink is replaced by a new Sink.
|
||||
Close() error
|
||||
}
|
||||
|
||||
type noopSink struct{}
|
||||
|
||||
func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil }
|
||||
func (ns *noopSink) Close() error { return nil }
|
||||
func (ns *noopSink) Write(*binlogpb.GrpcLogEntry) error { return nil }
|
||||
func (ns *noopSink) Close() error { return nil }
|
||||
|
||||
// newWriterSink creates a binary log sink with the given writer.
|
||||
//
|
||||
@@ -66,7 +66,7 @@ type writerSink struct {
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func (ws *writerSink) Write(e *pb.GrpcLogEntry) error {
|
||||
func (ws *writerSink) Write(e *binlogpb.GrpcLogEntry) error {
|
||||
b, err := proto.Marshal(e)
|
||||
if err != nil {
|
||||
grpclogLogger.Errorf("binary logging: failed to marshal proto message: %v", err)
|
||||
@@ -96,7 +96,7 @@ type bufferedSink struct {
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func (fs *bufferedSink) Write(e *pb.GrpcLogEntry) error {
|
||||
func (fs *bufferedSink) Write(e *binlogpb.GrpcLogEntry) error {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
if !fs.flusherStarted {
|
||||
|
63
vendor/google.golang.org/grpc/internal/buffer/unbounded.go
generated
vendored
63
vendor/google.golang.org/grpc/internal/buffer/unbounded.go
generated
vendored
@@ -18,7 +18,10 @@
|
||||
// Package buffer provides an implementation of an unbounded buffer.
|
||||
package buffer
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Unbounded is an implementation of an unbounded buffer which does not use
|
||||
// extra goroutines. This is typically used for passing updates from one entity
|
||||
@@ -28,42 +31,50 @@ import "sync"
|
||||
// the underlying mutex used for synchronization.
|
||||
//
|
||||
// Unbounded supports values of any type to be stored in it by using a channel
|
||||
// of `interface{}`. This means that a call to Put() incurs an extra memory
|
||||
// allocation, and also that users need a type assertion while reading. For
|
||||
// performance critical code paths, using Unbounded is strongly discouraged and
|
||||
// defining a new type specific implementation of this buffer is preferred. See
|
||||
// of `any`. This means that a call to Put() incurs an extra memory allocation,
|
||||
// and also that users need a type assertion while reading. For performance
|
||||
// critical code paths, using Unbounded is strongly discouraged and defining a
|
||||
// new type specific implementation of this buffer is preferred. See
|
||||
// internal/transport/transport.go for an example of this.
|
||||
type Unbounded struct {
|
||||
c chan interface{}
|
||||
c chan any
|
||||
closed bool
|
||||
closing bool
|
||||
mu sync.Mutex
|
||||
backlog []interface{}
|
||||
backlog []any
|
||||
}
|
||||
|
||||
// NewUnbounded returns a new instance of Unbounded.
|
||||
func NewUnbounded() *Unbounded {
|
||||
return &Unbounded{c: make(chan interface{}, 1)}
|
||||
return &Unbounded{c: make(chan any, 1)}
|
||||
}
|
||||
|
||||
var errBufferClosed = errors.New("Put called on closed buffer.Unbounded")
|
||||
|
||||
// Put adds t to the unbounded buffer.
|
||||
func (b *Unbounded) Put(t interface{}) {
|
||||
func (b *Unbounded) Put(t any) error {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closing {
|
||||
return errBufferClosed
|
||||
}
|
||||
if len(b.backlog) == 0 {
|
||||
select {
|
||||
case b.c <- t:
|
||||
b.mu.Unlock()
|
||||
return
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
}
|
||||
b.backlog = append(b.backlog, t)
|
||||
b.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load sends the earliest buffered data, if any, onto the read channel
|
||||
// returned by Get(). Users are expected to call this every time they read a
|
||||
// Load sends the earliest buffered data, if any, onto the read channel returned
|
||||
// by Get(). Users are expected to call this every time they successfully read a
|
||||
// value from the read channel.
|
||||
func (b *Unbounded) Load() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if len(b.backlog) > 0 {
|
||||
select {
|
||||
case b.c <- b.backlog[0]:
|
||||
@@ -71,8 +82,9 @@ func (b *Unbounded) Load() {
|
||||
b.backlog = b.backlog[1:]
|
||||
default:
|
||||
}
|
||||
} else if b.closing && !b.closed {
|
||||
close(b.c)
|
||||
}
|
||||
b.mu.Unlock()
|
||||
}
|
||||
|
||||
// Get returns a read channel on which values added to the buffer, via Put(),
|
||||
@@ -80,6 +92,25 @@ func (b *Unbounded) Load() {
|
||||
//
|
||||
// Upon reading a value from this channel, users are expected to call Load() to
|
||||
// send the next buffered value onto the channel if there is any.
|
||||
func (b *Unbounded) Get() <-chan interface{} {
|
||||
//
|
||||
// If the unbounded buffer is closed, the read channel returned by this method
|
||||
// is closed after all data is drained.
|
||||
func (b *Unbounded) Get() <-chan any {
|
||||
return b.c
|
||||
}
|
||||
|
||||
// Close closes the unbounded buffer. No subsequent data may be Put(), and the
|
||||
// channel returned from Get() will be closed after all the data is read and
|
||||
// Load() is called for the final time.
|
||||
func (b *Unbounded) Close() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closing {
|
||||
return
|
||||
}
|
||||
b.closing = true
|
||||
if len(b.backlog) == 0 {
|
||||
b.closed = true
|
||||
close(b.c)
|
||||
}
|
||||
}
|
||||
|
76
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
76
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
@@ -24,15 +24,14 @@
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -40,8 +39,11 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
db dbWrapper
|
||||
idGen idGenerator
|
||||
// IDGen is the global channelz entity ID generator. It should not be used
|
||||
// outside this package except by tests.
|
||||
IDGen IDGenerator
|
||||
|
||||
db dbWrapper
|
||||
// EntryPerPage defines the number of channelz entries to be shown on a web page.
|
||||
EntryPerPage = int64(50)
|
||||
curState int32
|
||||
@@ -52,14 +54,20 @@ var (
|
||||
func TurnOn() {
|
||||
if !IsOn() {
|
||||
db.set(newChannelMap())
|
||||
idGen.reset()
|
||||
IDGen.Reset()
|
||||
atomic.StoreInt32(&curState, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.ChannelzTurnOffForTesting = func() {
|
||||
atomic.StoreInt32(&curState, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// IsOn returns whether channelz data collection is on.
|
||||
func IsOn() bool {
|
||||
return atomic.CompareAndSwapInt32(&curState, 1, 1)
|
||||
return atomic.LoadInt32(&curState) == 1
|
||||
}
|
||||
|
||||
// SetMaxTraceEntry sets maximum number of trace entry per entity (i.e. channel/subchannel).
|
||||
@@ -97,43 +105,6 @@ func (d *dbWrapper) get() *channelMap {
|
||||
return d.DB
|
||||
}
|
||||
|
||||
// NewChannelzStorageForTesting initializes channelz data storage and id
|
||||
// generator for testing purposes.
|
||||
//
|
||||
// Returns a cleanup function to be invoked by the test, which waits for up to
|
||||
// 10s for all channelz state to be reset by the grpc goroutines when those
|
||||
// entities get closed. This cleanup function helps with ensuring that tests
|
||||
// don't mess up each other.
|
||||
func NewChannelzStorageForTesting() (cleanup func() error) {
|
||||
db.set(newChannelMap())
|
||||
idGen.reset()
|
||||
|
||||
return func() error {
|
||||
cm := db.get()
|
||||
if cm == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
ticker := time.NewTicker(10 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
cm.mu.RLock()
|
||||
topLevelChannels, servers, channels, subChannels, listenSockets, normalSockets := len(cm.topLevelChannels), len(cm.servers), len(cm.channels), len(cm.subChannels), len(cm.listenSockets), len(cm.normalSockets)
|
||||
cm.mu.RUnlock()
|
||||
|
||||
if err := ctx.Err(); err != nil {
|
||||
return fmt.Errorf("after 10s the channelz map has not been cleaned up yet, topchannels: %d, servers: %d, channels: %d, subchannels: %d, listen sockets: %d, normal sockets: %d", topLevelChannels, servers, channels, subChannels, listenSockets, normalSockets)
|
||||
}
|
||||
if topLevelChannels == 0 && servers == 0 && channels == 0 && subChannels == 0 && listenSockets == 0 && normalSockets == 0 {
|
||||
return nil
|
||||
}
|
||||
<-ticker.C
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetTopChannels returns a slice of top channel's ChannelMetric, along with a
|
||||
// boolean indicating whether there's more top channels to be queried for.
|
||||
//
|
||||
@@ -193,7 +164,7 @@ func GetServer(id int64) *ServerMetric {
|
||||
//
|
||||
// If channelz is not turned ON, the channelz database is not mutated.
|
||||
func RegisterChannel(c Channel, pid *Identifier, ref string) *Identifier {
|
||||
id := idGen.genID()
|
||||
id := IDGen.genID()
|
||||
var parent int64
|
||||
isTopChannel := true
|
||||
if pid != nil {
|
||||
@@ -229,7 +200,7 @@ func RegisterSubChannel(c Channel, pid *Identifier, ref string) (*Identifier, er
|
||||
if pid == nil {
|
||||
return nil, errors.New("a SubChannel's parent id cannot be nil")
|
||||
}
|
||||
id := idGen.genID()
|
||||
id := IDGen.genID()
|
||||
if !IsOn() {
|
||||
return newIdentifer(RefSubChannel, id, pid), nil
|
||||
}
|
||||
@@ -251,7 +222,7 @@ func RegisterSubChannel(c Channel, pid *Identifier, ref string) (*Identifier, er
|
||||
//
|
||||
// If channelz is not turned ON, the channelz database is not mutated.
|
||||
func RegisterServer(s Server, ref string) *Identifier {
|
||||
id := idGen.genID()
|
||||
id := IDGen.genID()
|
||||
if !IsOn() {
|
||||
return newIdentifer(RefServer, id, nil)
|
||||
}
|
||||
@@ -277,7 +248,7 @@ func RegisterListenSocket(s Socket, pid *Identifier, ref string) (*Identifier, e
|
||||
if pid == nil {
|
||||
return nil, errors.New("a ListenSocket's parent id cannot be 0")
|
||||
}
|
||||
id := idGen.genID()
|
||||
id := IDGen.genID()
|
||||
if !IsOn() {
|
||||
return newIdentifer(RefListenSocket, id, pid), nil
|
||||
}
|
||||
@@ -297,7 +268,7 @@ func RegisterNormalSocket(s Socket, pid *Identifier, ref string) (*Identifier, e
|
||||
if pid == nil {
|
||||
return nil, errors.New("a NormalSocket's parent id cannot be 0")
|
||||
}
|
||||
id := idGen.genID()
|
||||
id := IDGen.genID()
|
||||
if !IsOn() {
|
||||
return newIdentifer(RefNormalSocket, id, pid), nil
|
||||
}
|
||||
@@ -776,14 +747,17 @@ func (c *channelMap) GetServer(id int64) *ServerMetric {
|
||||
return sm
|
||||
}
|
||||
|
||||
type idGenerator struct {
|
||||
// IDGenerator is an incrementing atomic that tracks IDs for channelz entities.
|
||||
type IDGenerator struct {
|
||||
id int64
|
||||
}
|
||||
|
||||
func (i *idGenerator) reset() {
|
||||
// Reset resets the generated ID back to zero. Should only be used at
|
||||
// initialization or by tests sensitive to the ID number.
|
||||
func (i *IDGenerator) Reset() {
|
||||
atomic.StoreInt64(&i.id, 0)
|
||||
}
|
||||
|
||||
func (i *idGenerator) genID() int64 {
|
||||
func (i *IDGenerator) genID() int64 {
|
||||
return atomic.AddInt64(&i.id, 1)
|
||||
}
|
||||
|
12
vendor/google.golang.org/grpc/internal/channelz/logging.go
generated
vendored
12
vendor/google.golang.org/grpc/internal/channelz/logging.go
generated
vendored
@@ -31,7 +31,7 @@ func withParens(id *Identifier) string {
|
||||
}
|
||||
|
||||
// Info logs and adds a trace event if channelz is on.
|
||||
func Info(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
|
||||
func Info(l grpclog.DepthLoggerV2, id *Identifier, args ...any) {
|
||||
AddTraceEvent(l, id, 1, &TraceEventDesc{
|
||||
Desc: fmt.Sprint(args...),
|
||||
Severity: CtInfo,
|
||||
@@ -39,7 +39,7 @@ func Info(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Infof logs and adds a trace event if channelz is on.
|
||||
func Infof(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...interface{}) {
|
||||
func Infof(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...any) {
|
||||
AddTraceEvent(l, id, 1, &TraceEventDesc{
|
||||
Desc: fmt.Sprintf(format, args...),
|
||||
Severity: CtInfo,
|
||||
@@ -47,7 +47,7 @@ func Infof(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...inter
|
||||
}
|
||||
|
||||
// Warning logs and adds a trace event if channelz is on.
|
||||
func Warning(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
|
||||
func Warning(l grpclog.DepthLoggerV2, id *Identifier, args ...any) {
|
||||
AddTraceEvent(l, id, 1, &TraceEventDesc{
|
||||
Desc: fmt.Sprint(args...),
|
||||
Severity: CtWarning,
|
||||
@@ -55,7 +55,7 @@ func Warning(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Warningf logs and adds a trace event if channelz is on.
|
||||
func Warningf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...interface{}) {
|
||||
func Warningf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...any) {
|
||||
AddTraceEvent(l, id, 1, &TraceEventDesc{
|
||||
Desc: fmt.Sprintf(format, args...),
|
||||
Severity: CtWarning,
|
||||
@@ -63,7 +63,7 @@ func Warningf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...in
|
||||
}
|
||||
|
||||
// Error logs and adds a trace event if channelz is on.
|
||||
func Error(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
|
||||
func Error(l grpclog.DepthLoggerV2, id *Identifier, args ...any) {
|
||||
AddTraceEvent(l, id, 1, &TraceEventDesc{
|
||||
Desc: fmt.Sprint(args...),
|
||||
Severity: CtError,
|
||||
@@ -71,7 +71,7 @@ func Error(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Errorf logs and adds a trace event if channelz is on.
|
||||
func Errorf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...interface{}) {
|
||||
func Errorf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...any) {
|
||||
AddTraceEvent(l, id, 1, &TraceEventDesc{
|
||||
Desc: fmt.Sprintf(format, args...),
|
||||
Severity: CtError,
|
||||
|
5
vendor/google.golang.org/grpc/internal/channelz/types.go
generated
vendored
5
vendor/google.golang.org/grpc/internal/channelz/types.go
generated
vendored
@@ -628,6 +628,7 @@ type tracedChannel interface {
|
||||
|
||||
type channelTrace struct {
|
||||
cm *channelMap
|
||||
clearCalled bool
|
||||
createdTime time.Time
|
||||
eventCount int64
|
||||
mu sync.Mutex
|
||||
@@ -656,6 +657,10 @@ func (c *channelTrace) append(e *TraceEvent) {
|
||||
}
|
||||
|
||||
func (c *channelTrace) clear() {
|
||||
if c.clearCalled {
|
||||
return
|
||||
}
|
||||
c.clearCalled = true
|
||||
c.mu.Lock()
|
||||
for _, e := range c.events {
|
||||
if e.RefID != 0 {
|
||||
|
2
vendor/google.golang.org/grpc/internal/channelz/util_linux.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/channelz/util_linux.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
// GetSocketOption gets the socket option info of the conn.
|
||||
func GetSocketOption(socket interface{}) *SocketOptionData {
|
||||
func GetSocketOption(socket any) *SocketOptionData {
|
||||
c, ok := socket.(syscall.Conn)
|
||||
if !ok {
|
||||
return nil
|
||||
|
2
vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
generated
vendored
@@ -22,6 +22,6 @@
|
||||
package channelz
|
||||
|
||||
// GetSocketOption gets the socket option info of the conn.
|
||||
func GetSocketOption(c interface{}) *SocketOptionData {
|
||||
func GetSocketOption(c any) *SocketOptionData {
|
||||
return nil
|
||||
}
|
||||
|
8
vendor/google.golang.org/grpc/internal/credentials/credentials.go
generated
vendored
8
vendor/google.golang.org/grpc/internal/credentials/credentials.go
generated
vendored
@@ -25,12 +25,12 @@ import (
|
||||
type requestInfoKey struct{}
|
||||
|
||||
// NewRequestInfoContext creates a context with ri.
|
||||
func NewRequestInfoContext(ctx context.Context, ri interface{}) context.Context {
|
||||
func NewRequestInfoContext(ctx context.Context, ri any) context.Context {
|
||||
return context.WithValue(ctx, requestInfoKey{}, ri)
|
||||
}
|
||||
|
||||
// RequestInfoFromContext extracts the RequestInfo from ctx.
|
||||
func RequestInfoFromContext(ctx context.Context) interface{} {
|
||||
func RequestInfoFromContext(ctx context.Context) any {
|
||||
return ctx.Value(requestInfoKey{})
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ func RequestInfoFromContext(ctx context.Context) interface{} {
|
||||
type clientHandshakeInfoKey struct{}
|
||||
|
||||
// ClientHandshakeInfoFromContext extracts the ClientHandshakeInfo from ctx.
|
||||
func ClientHandshakeInfoFromContext(ctx context.Context) interface{} {
|
||||
func ClientHandshakeInfoFromContext(ctx context.Context) any {
|
||||
return ctx.Value(clientHandshakeInfoKey{})
|
||||
}
|
||||
|
||||
// NewClientHandshakeInfoContext creates a context with chi.
|
||||
func NewClientHandshakeInfoContext(ctx context.Context, chi interface{}) context.Context {
|
||||
func NewClientHandshakeInfoContext(ctx context.Context, chi any) context.Context {
|
||||
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
|
||||
}
|
||||
|
46
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
46
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
@@ -21,19 +21,49 @@ package envconfig
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
prefix = "GRPC_GO_"
|
||||
txtErrIgnoreStr = prefix + "IGNORE_TXT_ERRORS"
|
||||
advertiseCompressorsStr = prefix + "ADVERTISE_COMPRESSORS"
|
||||
)
|
||||
|
||||
var (
|
||||
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
|
||||
TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false")
|
||||
TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
|
||||
// AdvertiseCompressors is set if registered compressor should be advertised
|
||||
// ("GRPC_GO_ADVERTISE_COMPRESSORS" is not "false").
|
||||
AdvertiseCompressors = !strings.EqualFold(os.Getenv(advertiseCompressorsStr), "false")
|
||||
AdvertiseCompressors = boolFromEnv("GRPC_GO_ADVERTISE_COMPRESSORS", true)
|
||||
// RingHashCap indicates the maximum ring size which defaults to 4096
|
||||
// entries but may be overridden by setting the environment variable
|
||||
// "GRPC_RING_HASH_CAP". This does not override the default bounds
|
||||
// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
|
||||
RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
|
||||
// LeastRequestLB is set if we should support the least_request_experimental
|
||||
// LB policy, which can be enabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
|
||||
LeastRequestLB = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST", false)
|
||||
// ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS
|
||||
// handshakes that can be performed.
|
||||
ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100)
|
||||
)
|
||||
|
||||
func boolFromEnv(envVar string, def bool) bool {
|
||||
if def {
|
||||
// The default is true; return true unless the variable is "false".
|
||||
return !strings.EqualFold(os.Getenv(envVar), "false")
|
||||
}
|
||||
// The default is false; return false unless the variable is "true".
|
||||
return strings.EqualFold(os.Getenv(envVar), "true")
|
||||
}
|
||||
|
||||
func uint64FromEnv(envVar string, def, min, max uint64) uint64 {
|
||||
v, err := strconv.ParseUint(os.Getenv(envVar), 10, 64)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
if v < min {
|
||||
return min
|
||||
}
|
||||
if v > max {
|
||||
return max
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
6
vendor/google.golang.org/grpc/internal/envconfig/observability.go
generated
vendored
6
vendor/google.golang.org/grpc/internal/envconfig/observability.go
generated
vendored
@@ -28,9 +28,15 @@ const (
|
||||
var (
|
||||
// ObservabilityConfig is the json configuration for the gcp/observability
|
||||
// package specified directly in the envObservabilityConfig env var.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
ObservabilityConfig = os.Getenv(envObservabilityConfig)
|
||||
// ObservabilityConfigFile is the json configuration for the
|
||||
// gcp/observability specified in a file with the location specified in
|
||||
// envObservabilityConfigFile env var.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
ObservabilityConfigFile = os.Getenv(envObservabilityConfigFile)
|
||||
)
|
||||
|
47
vendor/google.golang.org/grpc/internal/envconfig/xds.go
generated
vendored
47
vendor/google.golang.org/grpc/internal/envconfig/xds.go
generated
vendored
@@ -20,7 +20,6 @@ package envconfig
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -36,16 +35,6 @@ const (
|
||||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileContentEnv = "GRPC_XDS_BOOTSTRAP_CONFIG"
|
||||
|
||||
ringHashSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH"
|
||||
clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
|
||||
aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
|
||||
rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC"
|
||||
outlierDetectionSupportEnv = "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION"
|
||||
federationEnv = "GRPC_EXPERIMENTAL_XDS_FEDERATION"
|
||||
rlsInXDSEnv = "GRPC_EXPERIMENTAL_XDS_RLS_LB"
|
||||
|
||||
c2pResolverTestOnlyTrafficDirectorURIEnv = "GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -61,41 +50,7 @@ var (
|
||||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileContent = os.Getenv(XDSBootstrapFileContentEnv)
|
||||
// XDSRingHash indicates whether ring hash support is enabled, which can be
|
||||
// disabled by setting the environment variable
|
||||
// "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" to "false".
|
||||
XDSRingHash = !strings.EqualFold(os.Getenv(ringHashSupportEnv), "false")
|
||||
// XDSClientSideSecurity is used to control processing of security
|
||||
// configuration on the client-side.
|
||||
//
|
||||
// Note that there is no env var protection for the server-side because we
|
||||
// have a brand new API on the server-side and users explicitly need to use
|
||||
// the new API to get security integration on the server.
|
||||
XDSClientSideSecurity = !strings.EqualFold(os.Getenv(clientSideSecuritySupportEnv), "false")
|
||||
// XDSAggregateAndDNS indicates whether processing of aggregated cluster
|
||||
// and DNS cluster is enabled, which can be enabled by setting the
|
||||
// environment variable
|
||||
// "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to
|
||||
// "true".
|
||||
XDSAggregateAndDNS = !strings.EqualFold(os.Getenv(aggregateAndDNSSupportEnv), "false")
|
||||
|
||||
// XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled,
|
||||
// which can be disabled by setting the environment variable
|
||||
// "GRPC_XDS_EXPERIMENTAL_RBAC" to "false".
|
||||
XDSRBAC = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false")
|
||||
// XDSOutlierDetection indicates whether outlier detection support is
|
||||
// enabled, which can be disabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "false".
|
||||
XDSOutlierDetection = !strings.EqualFold(os.Getenv(outlierDetectionSupportEnv), "false")
|
||||
// XDSFederation indicates whether federation support is enabled.
|
||||
XDSFederation = strings.EqualFold(os.Getenv(federationEnv), "true")
|
||||
|
||||
// XDSRLS indicates whether processing of Cluster Specifier plugins and
|
||||
// support for the RLS CLuster Specifier is enabled, which can be enabled by
|
||||
// setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to
|
||||
// "true".
|
||||
XDSRLS = strings.EqualFold(os.Getenv(rlsInXDSEnv), "true")
|
||||
|
||||
// C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing.
|
||||
C2PResolverTestOnlyTrafficDirectorURI = os.Getenv(c2pResolverTestOnlyTrafficDirectorURIEnv)
|
||||
C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI")
|
||||
)
|
||||
|
28
vendor/google.golang.org/grpc/internal/experimental.go
generated
vendored
Normal file
28
vendor/google.golang.org/grpc/internal/experimental.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
var (
|
||||
// WithRecvBufferPool is implemented by the grpc package and returns a dial
|
||||
// option to configure a shared buffer pool for a grpc.ClientConn.
|
||||
WithRecvBufferPool any // func (grpc.SharedBufferPool) grpc.DialOption
|
||||
|
||||
// RecvBufferPool is implemented by the grpc package and returns a server
|
||||
// option to configure a shared buffer pool for a grpc.Server.
|
||||
RecvBufferPool any // func (grpc.SharedBufferPool) grpc.ServerOption
|
||||
)
|
40
vendor/google.golang.org/grpc/internal/grpclog/grpclog.go
generated
vendored
40
vendor/google.golang.org/grpc/internal/grpclog/grpclog.go
generated
vendored
@@ -30,7 +30,7 @@ var Logger LoggerV2
|
||||
var DepthLogger DepthLoggerV2
|
||||
|
||||
// InfoDepth logs to the INFO log at the specified depth.
|
||||
func InfoDepth(depth int, args ...interface{}) {
|
||||
func InfoDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.InfoDepth(depth, args...)
|
||||
} else {
|
||||
@@ -39,7 +39,7 @@ func InfoDepth(depth int, args ...interface{}) {
|
||||
}
|
||||
|
||||
// WarningDepth logs to the WARNING log at the specified depth.
|
||||
func WarningDepth(depth int, args ...interface{}) {
|
||||
func WarningDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.WarningDepth(depth, args...)
|
||||
} else {
|
||||
@@ -48,7 +48,7 @@ func WarningDepth(depth int, args ...interface{}) {
|
||||
}
|
||||
|
||||
// ErrorDepth logs to the ERROR log at the specified depth.
|
||||
func ErrorDepth(depth int, args ...interface{}) {
|
||||
func ErrorDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.ErrorDepth(depth, args...)
|
||||
} else {
|
||||
@@ -57,7 +57,7 @@ func ErrorDepth(depth int, args ...interface{}) {
|
||||
}
|
||||
|
||||
// FatalDepth logs to the FATAL log at the specified depth.
|
||||
func FatalDepth(depth int, args ...interface{}) {
|
||||
func FatalDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.FatalDepth(depth, args...)
|
||||
} else {
|
||||
@@ -71,35 +71,35 @@ func FatalDepth(depth int, args ...interface{}) {
|
||||
// is defined here to avoid a circular dependency.
|
||||
type LoggerV2 interface {
|
||||
// Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
|
||||
Info(args ...interface{})
|
||||
Info(args ...any)
|
||||
// Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
Infoln(args ...interface{})
|
||||
Infoln(args ...any)
|
||||
// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
Infof(format string, args ...interface{})
|
||||
Infof(format string, args ...any)
|
||||
// Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
|
||||
Warning(args ...interface{})
|
||||
Warning(args ...any)
|
||||
// Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
Warningln(args ...interface{})
|
||||
Warningln(args ...any)
|
||||
// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
Warningf(format string, args ...interface{})
|
||||
Warningf(format string, args ...any)
|
||||
// Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
Error(args ...interface{})
|
||||
Error(args ...any)
|
||||
// Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
Errorln(args ...interface{})
|
||||
Errorln(args ...any)
|
||||
// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
Errorf(format string, args ...interface{})
|
||||
Errorf(format string, args ...any)
|
||||
// Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatal(args ...interface{})
|
||||
Fatal(args ...any)
|
||||
// Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalln(args ...interface{})
|
||||
Fatalln(args ...any)
|
||||
// Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalf(format string, args ...interface{})
|
||||
Fatalf(format string, args ...any)
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
V(l int) bool
|
||||
}
|
||||
@@ -116,11 +116,11 @@ type LoggerV2 interface {
|
||||
// later release.
|
||||
type DepthLoggerV2 interface {
|
||||
// InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
InfoDepth(depth int, args ...interface{})
|
||||
InfoDepth(depth int, args ...any)
|
||||
// WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
WarningDepth(depth int, args ...interface{})
|
||||
WarningDepth(depth int, args ...any)
|
||||
// ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
ErrorDepth(depth int, args ...interface{})
|
||||
ErrorDepth(depth int, args ...any)
|
||||
// FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
FatalDepth(depth int, args ...interface{})
|
||||
FatalDepth(depth int, args ...any)
|
||||
}
|
||||
|
20
vendor/google.golang.org/grpc/internal/grpclog/prefixLogger.go
generated
vendored
20
vendor/google.golang.org/grpc/internal/grpclog/prefixLogger.go
generated
vendored
@@ -31,7 +31,7 @@ type PrefixLogger struct {
|
||||
}
|
||||
|
||||
// Infof does info logging.
|
||||
func (pl *PrefixLogger) Infof(format string, args ...interface{}) {
|
||||
func (pl *PrefixLogger) Infof(format string, args ...any) {
|
||||
if pl != nil {
|
||||
// Handle nil, so the tests can pass in a nil logger.
|
||||
format = pl.prefix + format
|
||||
@@ -42,7 +42,7 @@ func (pl *PrefixLogger) Infof(format string, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Warningf does warning logging.
|
||||
func (pl *PrefixLogger) Warningf(format string, args ...interface{}) {
|
||||
func (pl *PrefixLogger) Warningf(format string, args ...any) {
|
||||
if pl != nil {
|
||||
format = pl.prefix + format
|
||||
pl.logger.WarningDepth(1, fmt.Sprintf(format, args...))
|
||||
@@ -52,7 +52,7 @@ func (pl *PrefixLogger) Warningf(format string, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Errorf does error logging.
|
||||
func (pl *PrefixLogger) Errorf(format string, args ...interface{}) {
|
||||
func (pl *PrefixLogger) Errorf(format string, args ...any) {
|
||||
if pl != nil {
|
||||
format = pl.prefix + format
|
||||
pl.logger.ErrorDepth(1, fmt.Sprintf(format, args...))
|
||||
@@ -62,7 +62,10 @@ func (pl *PrefixLogger) Errorf(format string, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Debugf does info logging at verbose level 2.
|
||||
func (pl *PrefixLogger) Debugf(format string, args ...interface{}) {
|
||||
func (pl *PrefixLogger) Debugf(format string, args ...any) {
|
||||
// TODO(6044): Refactor interfaces LoggerV2 and DepthLogger, and maybe
|
||||
// rewrite PrefixLogger a little to ensure that we don't use the global
|
||||
// `Logger` here, and instead use the `logger` field.
|
||||
if !Logger.V(2) {
|
||||
return
|
||||
}
|
||||
@@ -73,6 +76,15 @@ func (pl *PrefixLogger) Debugf(format string, args ...interface{}) {
|
||||
return
|
||||
}
|
||||
InfoDepth(1, fmt.Sprintf(format, args...))
|
||||
|
||||
}
|
||||
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
func (pl *PrefixLogger) V(l int) bool {
|
||||
// TODO(6044): Refactor interfaces LoggerV2 and DepthLogger, and maybe
|
||||
// rewrite PrefixLogger a little to ensure that we don't use the global
|
||||
// `Logger` here, and instead use the `logger` field.
|
||||
return Logger.V(l)
|
||||
}
|
||||
|
||||
// NewPrefixLogger creates a prefix logger with the given prefix.
|
||||
|
21
vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
generated
vendored
21
vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
generated
vendored
@@ -72,3 +72,24 @@ func Uint64() uint64 {
|
||||
defer mu.Unlock()
|
||||
return r.Uint64()
|
||||
}
|
||||
|
||||
// Uint32 implements rand.Uint32 on the grpcrand global source.
|
||||
func Uint32() uint32 {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
return r.Uint32()
|
||||
}
|
||||
|
||||
// ExpFloat64 implements rand.ExpFloat64 on the grpcrand global source.
|
||||
func ExpFloat64() float64 {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
return r.ExpFloat64()
|
||||
}
|
||||
|
||||
// Shuffle implements rand.Shuffle on the grpcrand global source.
|
||||
var Shuffle = func(n int, f func(int, int)) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
r.Shuffle(n, f)
|
||||
}
|
||||
|
100
vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
generated
vendored
Normal file
100
vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpcsync
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc/internal/buffer"
|
||||
)
|
||||
|
||||
// CallbackSerializer provides a mechanism to schedule callbacks in a
|
||||
// synchronized manner. It provides a FIFO guarantee on the order of execution
|
||||
// of scheduled callbacks. New callbacks can be scheduled by invoking the
|
||||
// Schedule() method.
|
||||
//
|
||||
// This type is safe for concurrent access.
|
||||
type CallbackSerializer struct {
|
||||
// done is closed once the serializer is shut down completely, i.e all
|
||||
// scheduled callbacks are executed and the serializer has deallocated all
|
||||
// its resources.
|
||||
done chan struct{}
|
||||
|
||||
callbacks *buffer.Unbounded
|
||||
}
|
||||
|
||||
// NewCallbackSerializer returns a new CallbackSerializer instance. The provided
|
||||
// context will be passed to the scheduled callbacks. Users should cancel the
|
||||
// provided context to shutdown the CallbackSerializer. It is guaranteed that no
|
||||
// callbacks will be added once this context is canceled, and any pending un-run
|
||||
// callbacks will be executed before the serializer is shut down.
|
||||
func NewCallbackSerializer(ctx context.Context) *CallbackSerializer {
|
||||
cs := &CallbackSerializer{
|
||||
done: make(chan struct{}),
|
||||
callbacks: buffer.NewUnbounded(),
|
||||
}
|
||||
go cs.run(ctx)
|
||||
return cs
|
||||
}
|
||||
|
||||
// Schedule adds a callback to be scheduled after existing callbacks are run.
|
||||
//
|
||||
// Callbacks are expected to honor the context when performing any blocking
|
||||
// operations, and should return early when the context is canceled.
|
||||
//
|
||||
// Return value indicates if the callback was successfully added to the list of
|
||||
// callbacks to be executed by the serializer. It is not possible to add
|
||||
// callbacks once the context passed to NewCallbackSerializer is cancelled.
|
||||
func (cs *CallbackSerializer) Schedule(f func(ctx context.Context)) bool {
|
||||
return cs.callbacks.Put(f) == nil
|
||||
}
|
||||
|
||||
func (cs *CallbackSerializer) run(ctx context.Context) {
|
||||
defer close(cs.done)
|
||||
|
||||
// TODO: when Go 1.21 is the oldest supported version, this loop and Close
|
||||
// can be replaced with:
|
||||
//
|
||||
// context.AfterFunc(ctx, cs.callbacks.Close)
|
||||
for ctx.Err() == nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Do nothing here. Next iteration of the for loop will not happen,
|
||||
// since ctx.Err() would be non-nil.
|
||||
case cb := <-cs.callbacks.Get():
|
||||
cs.callbacks.Load()
|
||||
cb.(func(context.Context))(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Close the buffer to prevent new callbacks from being added.
|
||||
cs.callbacks.Close()
|
||||
|
||||
// Run all pending callbacks.
|
||||
for cb := range cs.callbacks.Get() {
|
||||
cs.callbacks.Load()
|
||||
cb.(func(context.Context))(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Done returns a channel that is closed after the context passed to
|
||||
// NewCallbackSerializer is canceled and all callbacks have been executed.
|
||||
func (cs *CallbackSerializer) Done() <-chan struct{} {
|
||||
return cs.done
|
||||
}
|
121
vendor/google.golang.org/grpc/internal/grpcsync/pubsub.go
generated
vendored
Normal file
121
vendor/google.golang.org/grpc/internal/grpcsync/pubsub.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpcsync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Subscriber represents an entity that is subscribed to messages published on
|
||||
// a PubSub. It wraps the callback to be invoked by the PubSub when a new
|
||||
// message is published.
|
||||
type Subscriber interface {
|
||||
// OnMessage is invoked when a new message is published. Implementations
|
||||
// must not block in this method.
|
||||
OnMessage(msg any)
|
||||
}
|
||||
|
||||
// PubSub is a simple one-to-many publish-subscribe system that supports
|
||||
// messages of arbitrary type. It guarantees that messages are delivered in
|
||||
// the same order in which they were published.
|
||||
//
|
||||
// Publisher invokes the Publish() method to publish new messages, while
|
||||
// subscribers interested in receiving these messages register a callback
|
||||
// via the Subscribe() method.
|
||||
//
|
||||
// Once a PubSub is stopped, no more messages can be published, but any pending
|
||||
// published messages will be delivered to the subscribers. Done may be used
|
||||
// to determine when all published messages have been delivered.
|
||||
type PubSub struct {
|
||||
cs *CallbackSerializer
|
||||
|
||||
// Access to the below fields are guarded by this mutex.
|
||||
mu sync.Mutex
|
||||
msg any
|
||||
subscribers map[Subscriber]bool
|
||||
}
|
||||
|
||||
// NewPubSub returns a new PubSub instance. Users should cancel the
|
||||
// provided context to shutdown the PubSub.
|
||||
func NewPubSub(ctx context.Context) *PubSub {
|
||||
return &PubSub{
|
||||
cs: NewCallbackSerializer(ctx),
|
||||
subscribers: map[Subscriber]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe registers the provided Subscriber to the PubSub.
|
||||
//
|
||||
// If the PubSub contains a previously published message, the Subscriber's
|
||||
// OnMessage() callback will be invoked asynchronously with the existing
|
||||
// message to begin with, and subsequently for every newly published message.
|
||||
//
|
||||
// The caller is responsible for invoking the returned cancel function to
|
||||
// unsubscribe itself from the PubSub.
|
||||
func (ps *PubSub) Subscribe(sub Subscriber) (cancel func()) {
|
||||
ps.mu.Lock()
|
||||
defer ps.mu.Unlock()
|
||||
|
||||
ps.subscribers[sub] = true
|
||||
|
||||
if ps.msg != nil {
|
||||
msg := ps.msg
|
||||
ps.cs.Schedule(func(context.Context) {
|
||||
ps.mu.Lock()
|
||||
defer ps.mu.Unlock()
|
||||
if !ps.subscribers[sub] {
|
||||
return
|
||||
}
|
||||
sub.OnMessage(msg)
|
||||
})
|
||||
}
|
||||
|
||||
return func() {
|
||||
ps.mu.Lock()
|
||||
defer ps.mu.Unlock()
|
||||
delete(ps.subscribers, sub)
|
||||
}
|
||||
}
|
||||
|
||||
// Publish publishes the provided message to the PubSub, and invokes
|
||||
// callbacks registered by subscribers asynchronously.
|
||||
func (ps *PubSub) Publish(msg any) {
|
||||
ps.mu.Lock()
|
||||
defer ps.mu.Unlock()
|
||||
|
||||
ps.msg = msg
|
||||
for sub := range ps.subscribers {
|
||||
s := sub
|
||||
ps.cs.Schedule(func(context.Context) {
|
||||
ps.mu.Lock()
|
||||
defer ps.mu.Unlock()
|
||||
if !ps.subscribers[s] {
|
||||
return
|
||||
}
|
||||
s.OnMessage(msg)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Done returns a channel that is closed after the context passed to NewPubSub
|
||||
// is canceled and all updates have been sent to subscribers.
|
||||
func (ps *PubSub) Done() <-chan struct{} {
|
||||
return ps.cs.Done()
|
||||
}
|
278
vendor/google.golang.org/grpc/internal/idle/idle.go
generated
vendored
Normal file
278
vendor/google.golang.org/grpc/internal/idle/idle.go
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package idle contains a component for managing idleness (entering and exiting)
|
||||
// based on RPC activity.
|
||||
package idle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// For overriding in unit tests.
|
||||
var timeAfterFunc = func(d time.Duration, f func()) *time.Timer {
|
||||
return time.AfterFunc(d, f)
|
||||
}
|
||||
|
||||
// Enforcer is the functionality provided by grpc.ClientConn to enter
|
||||
// and exit from idle mode.
|
||||
type Enforcer interface {
|
||||
ExitIdleMode() error
|
||||
EnterIdleMode()
|
||||
}
|
||||
|
||||
// Manager implements idleness detection and calls the configured Enforcer to
|
||||
// enter/exit idle mode when appropriate. Must be created by NewManager.
|
||||
type Manager struct {
|
||||
// State accessed atomically.
|
||||
lastCallEndTime int64 // Unix timestamp in nanos; time when the most recent RPC completed.
|
||||
activeCallsCount int32 // Count of active RPCs; -math.MaxInt32 means channel is idle or is trying to get there.
|
||||
activeSinceLastTimerCheck int32 // Boolean; True if there was an RPC since the last timer callback.
|
||||
closed int32 // Boolean; True when the manager is closed.
|
||||
|
||||
// Can be accessed without atomics or mutex since these are set at creation
|
||||
// time and read-only after that.
|
||||
enforcer Enforcer // Functionality provided by grpc.ClientConn.
|
||||
timeout time.Duration
|
||||
|
||||
// idleMu is used to guarantee mutual exclusion in two scenarios:
|
||||
// - Opposing intentions:
|
||||
// - a: Idle timeout has fired and handleIdleTimeout() is trying to put
|
||||
// the channel in idle mode because the channel has been inactive.
|
||||
// - b: At the same time an RPC is made on the channel, and OnCallBegin()
|
||||
// is trying to prevent the channel from going idle.
|
||||
// - Competing intentions:
|
||||
// - The channel is in idle mode and there are multiple RPCs starting at
|
||||
// the same time, all trying to move the channel out of idle. Only one
|
||||
// of them should succeed in doing so, while the other RPCs should
|
||||
// piggyback on the first one and be successfully handled.
|
||||
idleMu sync.RWMutex
|
||||
actuallyIdle bool
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
// NewManager creates a new idleness manager implementation for the
|
||||
// given idle timeout. It begins in idle mode.
|
||||
func NewManager(enforcer Enforcer, timeout time.Duration) *Manager {
|
||||
return &Manager{
|
||||
enforcer: enforcer,
|
||||
timeout: timeout,
|
||||
actuallyIdle: true,
|
||||
activeCallsCount: -math.MaxInt32,
|
||||
}
|
||||
}
|
||||
|
||||
// resetIdleTimerLocked resets the idle timer to the given duration. Called
|
||||
// when exiting idle mode or when the timer fires and we need to reset it.
|
||||
func (m *Manager) resetIdleTimerLocked(d time.Duration) {
|
||||
if m.isClosed() || m.timeout == 0 || m.actuallyIdle {
|
||||
return
|
||||
}
|
||||
|
||||
// It is safe to ignore the return value from Reset() because this method is
|
||||
// only ever called from the timer callback or when exiting idle mode.
|
||||
if m.timer != nil {
|
||||
m.timer.Stop()
|
||||
}
|
||||
m.timer = timeAfterFunc(d, m.handleIdleTimeout)
|
||||
}
|
||||
|
||||
func (m *Manager) resetIdleTimer(d time.Duration) {
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
m.resetIdleTimerLocked(d)
|
||||
}
|
||||
|
||||
// handleIdleTimeout is the timer callback that is invoked upon expiry of the
|
||||
// configured idle timeout. The channel is considered inactive if there are no
|
||||
// ongoing calls and no RPC activity since the last time the timer fired.
|
||||
func (m *Manager) handleIdleTimeout() {
|
||||
if m.isClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
if atomic.LoadInt32(&m.activeCallsCount) > 0 {
|
||||
m.resetIdleTimer(m.timeout)
|
||||
return
|
||||
}
|
||||
|
||||
// There has been activity on the channel since we last got here. Reset the
|
||||
// timer and return.
|
||||
if atomic.LoadInt32(&m.activeSinceLastTimerCheck) == 1 {
|
||||
// Set the timer to fire after a duration of idle timeout, calculated
|
||||
// from the time the most recent RPC completed.
|
||||
atomic.StoreInt32(&m.activeSinceLastTimerCheck, 0)
|
||||
m.resetIdleTimer(time.Duration(atomic.LoadInt64(&m.lastCallEndTime)-time.Now().UnixNano()) + m.timeout)
|
||||
return
|
||||
}
|
||||
|
||||
// Now that we've checked that there has been no activity, attempt to enter
|
||||
// idle mode, which is very likely to succeed.
|
||||
if m.tryEnterIdleMode() {
|
||||
// Successfully entered idle mode. No timer needed until we exit idle.
|
||||
return
|
||||
}
|
||||
|
||||
// Failed to enter idle mode due to a concurrent RPC that kept the channel
|
||||
// active, or because of an error from the channel. Undo the attempt to
|
||||
// enter idle, and reset the timer to try again later.
|
||||
m.resetIdleTimer(m.timeout)
|
||||
}
|
||||
|
||||
// tryEnterIdleMode instructs the channel to enter idle mode. But before
|
||||
// that, it performs a last minute check to ensure that no new RPC has come in,
|
||||
// making the channel active.
|
||||
//
|
||||
// Return value indicates whether or not the channel moved to idle mode.
|
||||
//
|
||||
// Holds idleMu which ensures mutual exclusion with exitIdleMode.
|
||||
func (m *Manager) tryEnterIdleMode() bool {
|
||||
// Setting the activeCallsCount to -math.MaxInt32 indicates to OnCallBegin()
|
||||
// that the channel is either in idle mode or is trying to get there.
|
||||
if !atomic.CompareAndSwapInt32(&m.activeCallsCount, 0, -math.MaxInt32) {
|
||||
// This CAS operation can fail if an RPC started after we checked for
|
||||
// activity in the timer handler, or one was ongoing from before the
|
||||
// last time the timer fired, or if a test is attempting to enter idle
|
||||
// mode without checking. In all cases, abort going into idle mode.
|
||||
return false
|
||||
}
|
||||
// N.B. if we fail to enter idle mode after this, we must re-add
|
||||
// math.MaxInt32 to m.activeCallsCount.
|
||||
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
|
||||
if atomic.LoadInt32(&m.activeCallsCount) != -math.MaxInt32 {
|
||||
// We raced and lost to a new RPC. Very rare, but stop entering idle.
|
||||
atomic.AddInt32(&m.activeCallsCount, math.MaxInt32)
|
||||
return false
|
||||
}
|
||||
if atomic.LoadInt32(&m.activeSinceLastTimerCheck) == 1 {
|
||||
// A very short RPC could have come in (and also finished) after we
|
||||
// checked for calls count and activity in handleIdleTimeout(), but
|
||||
// before the CAS operation. So, we need to check for activity again.
|
||||
atomic.AddInt32(&m.activeCallsCount, math.MaxInt32)
|
||||
return false
|
||||
}
|
||||
|
||||
// No new RPCs have come in since we set the active calls count value to
|
||||
// -math.MaxInt32. And since we have the lock, it is safe to enter idle mode
|
||||
// unconditionally now.
|
||||
m.enforcer.EnterIdleMode()
|
||||
m.actuallyIdle = true
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *Manager) EnterIdleModeForTesting() {
|
||||
m.tryEnterIdleMode()
|
||||
}
|
||||
|
||||
// OnCallBegin is invoked at the start of every RPC.
|
||||
func (m *Manager) OnCallBegin() error {
|
||||
if m.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if atomic.AddInt32(&m.activeCallsCount, 1) > 0 {
|
||||
// Channel is not idle now. Set the activity bit and allow the call.
|
||||
atomic.StoreInt32(&m.activeSinceLastTimerCheck, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Channel is either in idle mode or is in the process of moving to idle
|
||||
// mode. Attempt to exit idle mode to allow this RPC.
|
||||
if err := m.ExitIdleMode(); err != nil {
|
||||
// Undo the increment to calls count, and return an error causing the
|
||||
// RPC to fail.
|
||||
atomic.AddInt32(&m.activeCallsCount, -1)
|
||||
return err
|
||||
}
|
||||
|
||||
atomic.StoreInt32(&m.activeSinceLastTimerCheck, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExitIdleMode instructs m to call the enforcer's ExitIdleMode and update m's
|
||||
// internal state.
|
||||
func (m *Manager) ExitIdleMode() error {
|
||||
// Holds idleMu which ensures mutual exclusion with tryEnterIdleMode.
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
|
||||
if m.isClosed() || !m.actuallyIdle {
|
||||
// This can happen in three scenarios:
|
||||
// - handleIdleTimeout() set the calls count to -math.MaxInt32 and called
|
||||
// tryEnterIdleMode(). But before the latter could grab the lock, an RPC
|
||||
// came in and OnCallBegin() noticed that the calls count is negative.
|
||||
// - Channel is in idle mode, and multiple new RPCs come in at the same
|
||||
// time, all of them notice a negative calls count in OnCallBegin and get
|
||||
// here. The first one to get the lock would got the channel to exit idle.
|
||||
// - Channel is not in idle mode, and the user calls Connect which calls
|
||||
// m.ExitIdleMode.
|
||||
//
|
||||
// In any case, there is nothing to do here.
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := m.enforcer.ExitIdleMode(); err != nil {
|
||||
return fmt.Errorf("failed to exit idle mode: %w", err)
|
||||
}
|
||||
|
||||
// Undo the idle entry process. This also respects any new RPC attempts.
|
||||
atomic.AddInt32(&m.activeCallsCount, math.MaxInt32)
|
||||
m.actuallyIdle = false
|
||||
|
||||
// Start a new timer to fire after the configured idle timeout.
|
||||
m.resetIdleTimerLocked(m.timeout)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnCallEnd is invoked at the end of every RPC.
|
||||
func (m *Manager) OnCallEnd() {
|
||||
if m.isClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
// Record the time at which the most recent call finished.
|
||||
atomic.StoreInt64(&m.lastCallEndTime, time.Now().UnixNano())
|
||||
|
||||
// Decrement the active calls count. This count can temporarily go negative
|
||||
// when the timer callback is in the process of moving the channel to idle
|
||||
// mode, but one or more RPCs come in and complete before the timer callback
|
||||
// can get done with the process of moving to idle mode.
|
||||
atomic.AddInt32(&m.activeCallsCount, -1)
|
||||
}
|
||||
|
||||
func (m *Manager) isClosed() bool {
|
||||
return atomic.LoadInt32(&m.closed) == 1
|
||||
}
|
||||
|
||||
func (m *Manager) Close() {
|
||||
atomic.StoreInt32(&m.closed, 1)
|
||||
|
||||
m.idleMu.Lock()
|
||||
if m.timer != nil {
|
||||
m.timer.Stop()
|
||||
m.timer = nil
|
||||
}
|
||||
m.idleMu.Unlock()
|
||||
}
|
87
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
87
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
@@ -30,7 +30,7 @@ import (
|
||||
|
||||
var (
|
||||
// WithHealthCheckFunc is set by dialoptions.go
|
||||
WithHealthCheckFunc interface{} // func (HealthChecker) DialOption
|
||||
WithHealthCheckFunc any // func (HealthChecker) DialOption
|
||||
// HealthCheckFunc is used to provide client-side LB channel health checking
|
||||
HealthCheckFunc HealthChecker
|
||||
// BalancerUnregister is exported by package balancer to unregister a balancer.
|
||||
@@ -38,8 +38,12 @@ var (
|
||||
// KeepaliveMinPingTime is the minimum ping interval. This must be 10s by
|
||||
// default, but tests may wish to set it lower for convenience.
|
||||
KeepaliveMinPingTime = 10 * time.Second
|
||||
// KeepaliveMinServerPingTime is the minimum ping interval for servers.
|
||||
// This must be 1s by default, but tests may wish to set it lower for
|
||||
// convenience.
|
||||
KeepaliveMinServerPingTime = time.Second
|
||||
// ParseServiceConfig parses a JSON representation of the service config.
|
||||
ParseServiceConfig interface{} // func(string) *serviceconfig.ParseResult
|
||||
ParseServiceConfig any // func(string) *serviceconfig.ParseResult
|
||||
// EqualServiceConfigForTesting is for testing service config generation and
|
||||
// parsing. Both a and b should be returned by ParseServiceConfig.
|
||||
// This function compares the config without rawJSON stripped, in case the
|
||||
@@ -49,44 +53,86 @@ var (
|
||||
// given name. This is set by package certprovider for use from xDS
|
||||
// bootstrap code while parsing certificate provider configs in the
|
||||
// bootstrap file.
|
||||
GetCertificateProviderBuilder interface{} // func(string) certprovider.Builder
|
||||
GetCertificateProviderBuilder any // func(string) certprovider.Builder
|
||||
// GetXDSHandshakeInfoForTesting returns a pointer to the xds.HandshakeInfo
|
||||
// stored in the passed in attributes. This is set by
|
||||
// credentials/xds/xds.go.
|
||||
GetXDSHandshakeInfoForTesting interface{} // func (*attributes.Attributes) *xds.HandshakeInfo
|
||||
GetXDSHandshakeInfoForTesting any // func (*attributes.Attributes) *xds.HandshakeInfo
|
||||
// GetServerCredentials returns the transport credentials configured on a
|
||||
// gRPC server. An xDS-enabled server needs to know what type of credentials
|
||||
// is configured on the underlying gRPC server. This is set by server.go.
|
||||
GetServerCredentials interface{} // func (*grpc.Server) credentials.TransportCredentials
|
||||
GetServerCredentials any // func (*grpc.Server) credentials.TransportCredentials
|
||||
// CanonicalString returns the canonical string of the code defined here:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/statuscodes.md.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
CanonicalString any // func (codes.Code) string
|
||||
// DrainServerTransports initiates a graceful close of existing connections
|
||||
// on a gRPC server accepted on the provided listener address. An
|
||||
// xDS-enabled server invokes this method on a grpc.Server when a particular
|
||||
// listener moves to "not-serving" mode.
|
||||
DrainServerTransports interface{} // func(*grpc.Server, string)
|
||||
DrainServerTransports any // func(*grpc.Server, string)
|
||||
// IsRegisteredMethod returns whether the passed in method is registered as
|
||||
// a method on the server.
|
||||
IsRegisteredMethod any // func(*grpc.Server, string) bool
|
||||
// ServerFromContext returns the server from the context.
|
||||
ServerFromContext any // func(context.Context) *grpc.Server
|
||||
// AddGlobalServerOptions adds an array of ServerOption that will be
|
||||
// effective globally for newly created servers. The priority will be: 1.
|
||||
// user-provided; 2. this method; 3. default values.
|
||||
AddGlobalServerOptions interface{} // func(opt ...ServerOption)
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
AddGlobalServerOptions any // func(opt ...ServerOption)
|
||||
// ClearGlobalServerOptions clears the array of extra ServerOption. This
|
||||
// method is useful in testing and benchmarking.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
ClearGlobalServerOptions func()
|
||||
// AddGlobalDialOptions adds an array of DialOption that will be effective
|
||||
// globally for newly created client channels. The priority will be: 1.
|
||||
// user-provided; 2. this method; 3. default values.
|
||||
AddGlobalDialOptions interface{} // func(opt ...DialOption)
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
AddGlobalDialOptions any // func(opt ...DialOption)
|
||||
// DisableGlobalDialOptions returns a DialOption that prevents the
|
||||
// ClientConn from applying the global DialOptions (set via
|
||||
// AddGlobalDialOptions).
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
DisableGlobalDialOptions any // func() grpc.DialOption
|
||||
// ClearGlobalDialOptions clears the array of extra DialOption. This
|
||||
// method is useful in testing and benchmarking.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
ClearGlobalDialOptions func()
|
||||
// JoinDialOptions combines the dial options passed as arguments into a
|
||||
// single dial option.
|
||||
JoinDialOptions any // func(...grpc.DialOption) grpc.DialOption
|
||||
// JoinServerOptions combines the server options passed as arguments into a
|
||||
// single server option.
|
||||
JoinServerOptions interface{} // func(...grpc.ServerOption) grpc.ServerOption
|
||||
JoinServerOptions any // func(...grpc.ServerOption) grpc.ServerOption
|
||||
|
||||
// WithBinaryLogger returns a DialOption that specifies the binary logger
|
||||
// for a ClientConn.
|
||||
WithBinaryLogger interface{} // func(binarylog.Logger) grpc.DialOption
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
WithBinaryLogger any // func(binarylog.Logger) grpc.DialOption
|
||||
// BinaryLogger returns a ServerOption that can set the binary logger for a
|
||||
// server.
|
||||
BinaryLogger interface{} // func(binarylog.Logger) grpc.ServerOption
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
BinaryLogger any // func(binarylog.Logger) grpc.ServerOption
|
||||
|
||||
// SubscribeToConnectivityStateChanges adds a grpcsync.Subscriber to a provided grpc.ClientConn
|
||||
SubscribeToConnectivityStateChanges any // func(*grpc.ClientConn, grpcsync.Subscriber)
|
||||
|
||||
// NewXDSResolverWithConfigForTesting creates a new xds resolver builder using
|
||||
// the provided xds bootstrap config instead of the global configuration from
|
||||
@@ -97,7 +143,7 @@ var (
|
||||
//
|
||||
// This function should ONLY be used for testing and may not work with some
|
||||
// other features, including the CSDS service.
|
||||
NewXDSResolverWithConfigForTesting interface{} // func([]byte) (resolver.Builder, error)
|
||||
NewXDSResolverWithConfigForTesting any // func([]byte) (resolver.Builder, error)
|
||||
|
||||
// RegisterRLSClusterSpecifierPluginForTesting registers the RLS Cluster
|
||||
// Specifier Plugin for testing purposes, regardless of the XDSRLS environment
|
||||
@@ -127,6 +173,21 @@ var (
|
||||
//
|
||||
// TODO: Remove this function once the RBAC env var is removed.
|
||||
UnregisterRBACHTTPFilterForTesting func()
|
||||
|
||||
// ORCAAllowAnyMinReportingInterval is for examples/orca use ONLY.
|
||||
ORCAAllowAnyMinReportingInterval any // func(so *orca.ServiceOptions)
|
||||
|
||||
// GRPCResolverSchemeExtraMetadata determines when gRPC will add extra
|
||||
// metadata to RPCs.
|
||||
GRPCResolverSchemeExtraMetadata string = "xds"
|
||||
|
||||
// EnterIdleModeForTesting gets the ClientConn to enter IDLE mode.
|
||||
EnterIdleModeForTesting any // func(*grpc.ClientConn)
|
||||
|
||||
// ExitIdleModeForTesting gets the ClientConn to exit IDLE mode.
|
||||
ExitIdleModeForTesting any // func(*grpc.ClientConn) error
|
||||
|
||||
ChannelzTurnOffForTesting func()
|
||||
)
|
||||
|
||||
// HealthChecker defines the signature of the client-side LB channel health checking function.
|
||||
@@ -137,7 +198,7 @@ var (
|
||||
//
|
||||
// The health checking protocol is defined at:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/health-checking.md
|
||||
type HealthChecker func(ctx context.Context, newStream func(string) (interface{}, error), setConnectivityState func(connectivity.State, error), serviceName string) error
|
||||
type HealthChecker func(ctx context.Context, newStream func(string) (any, error), setConnectivityState func(connectivity.State, error), serviceName string) error
|
||||
|
||||
const (
|
||||
// CredsBundleModeFallback switches GoogleDefaultCreds to fallback mode.
|
||||
|
64
vendor/google.golang.org/grpc/internal/metadata/metadata.go
generated
vendored
64
vendor/google.golang.org/grpc/internal/metadata/metadata.go
generated
vendored
@@ -35,7 +35,7 @@ const mdKey = mdKeyType("grpc.internal.address.metadata")
|
||||
|
||||
type mdValue metadata.MD
|
||||
|
||||
func (m mdValue) Equal(o interface{}) bool {
|
||||
func (m mdValue) Equal(o any) bool {
|
||||
om, ok := o.(mdValue)
|
||||
if !ok {
|
||||
return false
|
||||
@@ -76,33 +76,11 @@ func Set(addr resolver.Address, md metadata.MD) resolver.Address {
|
||||
return addr
|
||||
}
|
||||
|
||||
// Validate returns an error if the input md contains invalid keys or values.
|
||||
//
|
||||
// If the header is not a pseudo-header, the following items are checked:
|
||||
// - header names must contain one or more characters from this set [0-9 a-z _ - .].
|
||||
// - if the header-name ends with a "-bin" suffix, no validation of the header value is performed.
|
||||
// - otherwise, the header value must contain one or more characters from the set [%x20-%x7E].
|
||||
// Validate validates every pair in md with ValidatePair.
|
||||
func Validate(md metadata.MD) error {
|
||||
for k, vals := range md {
|
||||
// pseudo-header will be ignored
|
||||
if k[0] == ':' {
|
||||
continue
|
||||
}
|
||||
// check key, for i that saving a conversion if not using for range
|
||||
for i := 0; i < len(k); i++ {
|
||||
r := k[i]
|
||||
if !(r >= 'a' && r <= 'z') && !(r >= '0' && r <= '9') && r != '.' && r != '-' && r != '_' {
|
||||
return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", k)
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(k, "-bin") {
|
||||
continue
|
||||
}
|
||||
// check value
|
||||
for _, val := range vals {
|
||||
if hasNotPrintable(val) {
|
||||
return fmt.Errorf("header key %q contains value with non-printable ASCII characters", k)
|
||||
}
|
||||
if err := ValidatePair(k, vals...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -118,3 +96,37 @@ func hasNotPrintable(msg string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidatePair validate a key-value pair with the following rules (the pseudo-header will be skipped) :
|
||||
//
|
||||
// - key must contain one or more characters.
|
||||
// - the characters in the key must be contained in [0-9 a-z _ - .].
|
||||
// - if the key ends with a "-bin" suffix, no validation of the corresponding value is performed.
|
||||
// - the characters in the every value must be printable (in [%x20-%x7E]).
|
||||
func ValidatePair(key string, vals ...string) error {
|
||||
// key should not be empty
|
||||
if key == "" {
|
||||
return fmt.Errorf("there is an empty key in the header")
|
||||
}
|
||||
// pseudo-header will be ignored
|
||||
if key[0] == ':' {
|
||||
return nil
|
||||
}
|
||||
// check key, for i that saving a conversion if not using for range
|
||||
for i := 0; i < len(key); i++ {
|
||||
r := key[i]
|
||||
if !(r >= 'a' && r <= 'z') && !(r >= '0' && r <= '9') && r != '.' && r != '-' && r != '_' {
|
||||
return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", key)
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(key, "-bin") {
|
||||
return nil
|
||||
}
|
||||
// check value
|
||||
for _, val := range vals {
|
||||
if hasNotPrintable(val) {
|
||||
return fmt.Errorf("header key %q contains value with non-printable ASCII characters", key)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
2
vendor/google.golang.org/grpc/internal/pretty/pretty.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/pretty/pretty.go
generated
vendored
@@ -35,7 +35,7 @@ const jsonIndent = " "
|
||||
// ToJSON marshals the input into a json string.
|
||||
//
|
||||
// If marshal fails, it falls back to fmt.Sprintf("%+v").
|
||||
func ToJSON(e interface{}) string {
|
||||
func ToJSON(e any) string {
|
||||
switch ee := e.(type) {
|
||||
case protov1.Message:
|
||||
mm := jsonpb.Marshaler{Indent: jsonIndent}
|
||||
|
4
vendor/google.golang.org/grpc/internal/resolver/config_selector.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/resolver/config_selector.go
generated
vendored
@@ -92,7 +92,7 @@ type ClientStream interface {
|
||||
// calling RecvMsg on the same stream at the same time, but it is not safe
|
||||
// to call SendMsg on the same stream in different goroutines. It is also
|
||||
// not safe to call CloseSend concurrently with SendMsg.
|
||||
SendMsg(m interface{}) error
|
||||
SendMsg(m any) error
|
||||
// RecvMsg blocks until it receives a message into m or the stream is
|
||||
// done. It returns io.EOF when the stream completes successfully. On
|
||||
// any other error, the stream is aborted and the error contains the RPC
|
||||
@@ -101,7 +101,7 @@ type ClientStream interface {
|
||||
// It is safe to have a goroutine calling SendMsg and another goroutine
|
||||
// calling RecvMsg on the same stream at the same time, but it is not
|
||||
// safe to call RecvMsg on the same stream in different goroutines.
|
||||
RecvMsg(m interface{}) error
|
||||
RecvMsg(m any) error
|
||||
}
|
||||
|
||||
// ClientInterceptor is an interceptor for gRPC client streams.
|
||||
|
139
vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
generated
vendored
139
vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
generated
vendored
@@ -23,7 +23,6 @@ package dns
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
@@ -37,6 +36,7 @@ import (
|
||||
"google.golang.org/grpc/internal/backoff"
|
||||
"google.golang.org/grpc/internal/envconfig"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/internal/resolver/dns/internal"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
@@ -47,53 +47,37 @@ var EnableSRVLookups = false
|
||||
|
||||
var logger = grpclog.Component("dns")
|
||||
|
||||
// Globals to stub out in tests. TODO: Perhaps these two can be combined into a
|
||||
// single variable for testing the resolver?
|
||||
var (
|
||||
newTimer = time.NewTimer
|
||||
newTimerDNSResRate = time.NewTimer
|
||||
)
|
||||
|
||||
func init() {
|
||||
resolver.Register(NewBuilder())
|
||||
internal.TimeAfterFunc = time.After
|
||||
internal.NewNetResolver = newNetResolver
|
||||
internal.AddressDialer = addressDialer
|
||||
}
|
||||
|
||||
const (
|
||||
defaultPort = "443"
|
||||
defaultDNSSvrPort = "53"
|
||||
golang = "GO"
|
||||
// txtPrefix is the prefix string to be prepended to the host name for txt record lookup.
|
||||
// txtPrefix is the prefix string to be prepended to the host name for txt
|
||||
// record lookup.
|
||||
txtPrefix = "_grpc_config."
|
||||
// In DNS, service config is encoded in a TXT record via the mechanism
|
||||
// described in RFC-1464 using the attribute name grpc_config.
|
||||
txtAttribute = "grpc_config="
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingAddr = errors.New("dns resolver: missing address")
|
||||
|
||||
// Addresses ending with a colon that is supposed to be the separator
|
||||
// between host and port is not allowed. E.g. "::" is a valid address as
|
||||
// it is an IPv6 address (host only) and "[::]:" is invalid as it ends with
|
||||
// a colon as the host and port separator
|
||||
errEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
|
||||
)
|
||||
|
||||
var (
|
||||
defaultResolver netResolver = net.DefaultResolver
|
||||
// To prevent excessive re-resolution, we enforce a rate limit on DNS
|
||||
// resolution requests.
|
||||
minDNSResRate = 30 * time.Second
|
||||
)
|
||||
|
||||
var customAuthorityDialler = func(authority string) func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
var addressDialer = func(address string) func(context.Context, string, string) (net.Conn, error) {
|
||||
return func(ctx context.Context, network, _ string) (net.Conn, error) {
|
||||
var dialer net.Dialer
|
||||
return dialer.DialContext(ctx, network, authority)
|
||||
return dialer.DialContext(ctx, network, address)
|
||||
}
|
||||
}
|
||||
|
||||
var customAuthorityResolver = func(authority string) (netResolver, error) {
|
||||
var newNetResolver = func(authority string) (internal.NetResolver, error) {
|
||||
if authority == "" {
|
||||
return net.DefaultResolver, nil
|
||||
}
|
||||
|
||||
host, port, err := parseTarget(authority, defaultDNSSvrPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -103,7 +87,7 @@ var customAuthorityResolver = func(authority string) (netResolver, error) {
|
||||
|
||||
return &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: customAuthorityDialler(authorityWithPort),
|
||||
Dial: internal.AddressDialer(authorityWithPort),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -114,9 +98,10 @@ func NewBuilder() resolver.Builder {
|
||||
|
||||
type dnsBuilder struct{}
|
||||
|
||||
// Build creates and starts a DNS resolver that watches the name resolution of the target.
|
||||
// Build creates and starts a DNS resolver that watches the name resolution of
|
||||
// the target.
|
||||
func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
||||
host, port, err := parseTarget(target.Endpoint, defaultPort)
|
||||
host, port, err := parseTarget(target.Endpoint(), defaultPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -140,13 +125,9 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
|
||||
disableServiceConfig: opts.DisableServiceConfig,
|
||||
}
|
||||
|
||||
if target.Authority == "" {
|
||||
d.resolver = defaultResolver
|
||||
} else {
|
||||
d.resolver, err = customAuthorityResolver(target.Authority)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.resolver, err = internal.NewNetResolver(target.URL.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.wg.Add(1)
|
||||
@@ -159,12 +140,6 @@ func (b *dnsBuilder) Scheme() string {
|
||||
return "dns"
|
||||
}
|
||||
|
||||
type netResolver interface {
|
||||
LookupHost(ctx context.Context, host string) (addrs []string, err error)
|
||||
LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
|
||||
LookupTXT(ctx context.Context, name string) (txts []string, err error)
|
||||
}
|
||||
|
||||
// deadResolver is a resolver that does nothing.
|
||||
type deadResolver struct{}
|
||||
|
||||
@@ -176,23 +151,26 @@ func (deadResolver) Close() {}
|
||||
type dnsResolver struct {
|
||||
host string
|
||||
port string
|
||||
resolver netResolver
|
||||
resolver internal.NetResolver
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
cc resolver.ClientConn
|
||||
// rn channel is used by ResolveNow() to force an immediate resolution of the target.
|
||||
// rn channel is used by ResolveNow() to force an immediate resolution of the
|
||||
// target.
|
||||
rn chan struct{}
|
||||
// wg is used to enforce Close() to return after the watcher() goroutine has finished.
|
||||
// Otherwise, data race will be possible. [Race Example] in dns_resolver_test we
|
||||
// replace the real lookup functions with mocked ones to facilitate testing.
|
||||
// If Close() doesn't wait for watcher() goroutine finishes, race detector sometimes
|
||||
// will warns lookup (READ the lookup function pointers) inside watcher() goroutine
|
||||
// has data race with replaceNetFunc (WRITE the lookup function pointers).
|
||||
// wg is used to enforce Close() to return after the watcher() goroutine has
|
||||
// finished. Otherwise, data race will be possible. [Race Example] in
|
||||
// dns_resolver_test we replace the real lookup functions with mocked ones to
|
||||
// facilitate testing. If Close() doesn't wait for watcher() goroutine
|
||||
// finishes, race detector sometimes will warns lookup (READ the lookup
|
||||
// function pointers) inside watcher() goroutine has data race with
|
||||
// replaceNetFunc (WRITE the lookup function pointers).
|
||||
wg sync.WaitGroup
|
||||
disableServiceConfig bool
|
||||
}
|
||||
|
||||
// ResolveNow invoke an immediate resolution of the target that this dnsResolver watches.
|
||||
// ResolveNow invoke an immediate resolution of the target that this
|
||||
// dnsResolver watches.
|
||||
func (d *dnsResolver) ResolveNow(resolver.ResolveNowOptions) {
|
||||
select {
|
||||
case d.rn <- struct{}{}:
|
||||
@@ -218,28 +196,27 @@ func (d *dnsResolver) watcher() {
|
||||
err = d.cc.UpdateState(*state)
|
||||
}
|
||||
|
||||
var timer *time.Timer
|
||||
var waitTime time.Duration
|
||||
if err == nil {
|
||||
// Success resolving, wait for the next ResolveNow. However, also wait 30 seconds at the very least
|
||||
// to prevent constantly re-resolving.
|
||||
// Success resolving, wait for the next ResolveNow. However, also wait 30
|
||||
// seconds at the very least to prevent constantly re-resolving.
|
||||
backoffIndex = 1
|
||||
timer = newTimerDNSResRate(minDNSResRate)
|
||||
waitTime = internal.MinResolutionRate
|
||||
select {
|
||||
case <-d.ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
case <-d.rn:
|
||||
}
|
||||
} else {
|
||||
// Poll on an error found in DNS Resolver or an error received from ClientConn.
|
||||
timer = newTimer(backoff.DefaultExponential.Backoff(backoffIndex))
|
||||
// Poll on an error found in DNS Resolver or an error received from
|
||||
// ClientConn.
|
||||
waitTime = backoff.DefaultExponential.Backoff(backoffIndex)
|
||||
backoffIndex++
|
||||
}
|
||||
select {
|
||||
case <-d.ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
case <-timer.C:
|
||||
case <-internal.TimeAfterFunc(waitTime):
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,7 +255,8 @@ func (d *dnsResolver) lookupSRV() ([]resolver.Address, error) {
|
||||
}
|
||||
|
||||
func handleDNSError(err error, lookupType string) error {
|
||||
if dnsErr, ok := err.(*net.DNSError); ok && !dnsErr.IsTimeout && !dnsErr.IsTemporary {
|
||||
dnsErr, ok := err.(*net.DNSError)
|
||||
if ok && !dnsErr.IsTimeout && !dnsErr.IsTemporary {
|
||||
// Timeouts and temporary errors should be communicated to gRPC to
|
||||
// attempt another DNS query (with backoff). Other errors should be
|
||||
// suppressed (they may represent the absence of a TXT record).
|
||||
@@ -307,10 +285,12 @@ func (d *dnsResolver) lookupTXT() *serviceconfig.ParseResult {
|
||||
res += s
|
||||
}
|
||||
|
||||
// TXT record must have "grpc_config=" attribute in order to be used as service config.
|
||||
// TXT record must have "grpc_config=" attribute in order to be used as
|
||||
// service config.
|
||||
if !strings.HasPrefix(res, txtAttribute) {
|
||||
logger.Warningf("dns: TXT record %v missing %v attribute", res, txtAttribute)
|
||||
// This is not an error; it is the equivalent of not having a service config.
|
||||
// This is not an error; it is the equivalent of not having a service
|
||||
// config.
|
||||
return nil
|
||||
}
|
||||
sc := canaryingSC(strings.TrimPrefix(res, txtAttribute))
|
||||
@@ -352,9 +332,10 @@ func (d *dnsResolver) lookup() (*resolver.State, error) {
|
||||
return &state, nil
|
||||
}
|
||||
|
||||
// formatIP returns ok = false if addr is not a valid textual representation of an IP address.
|
||||
// If addr is an IPv4 address, return the addr and ok = true.
|
||||
// If addr is an IPv6 address, return the addr enclosed in square brackets and ok = true.
|
||||
// formatIP returns ok = false if addr is not a valid textual representation of
|
||||
// an IP address. If addr is an IPv4 address, return the addr and ok = true.
|
||||
// If addr is an IPv6 address, return the addr enclosed in square brackets and
|
||||
// ok = true.
|
||||
func formatIP(addr string) (addrIP string, ok bool) {
|
||||
ip := net.ParseIP(addr)
|
||||
if ip == nil {
|
||||
@@ -366,10 +347,10 @@ func formatIP(addr string) (addrIP string, ok bool) {
|
||||
return "[" + addr + "]", true
|
||||
}
|
||||
|
||||
// parseTarget takes the user input target string and default port, returns formatted host and port info.
|
||||
// If target doesn't specify a port, set the port to be the defaultPort.
|
||||
// If target is in IPv6 format and host-name is enclosed in square brackets, brackets
|
||||
// are stripped when setting the host.
|
||||
// parseTarget takes the user input target string and default port, returns
|
||||
// formatted host and port info. If target doesn't specify a port, set the port
|
||||
// to be the defaultPort. If target is in IPv6 format and host-name is enclosed
|
||||
// in square brackets, brackets are stripped when setting the host.
|
||||
// examples:
|
||||
// target: "www.google.com" defaultPort: "443" returns host: "www.google.com", port: "443"
|
||||
// target: "ipv4-host:80" defaultPort: "443" returns host: "ipv4-host", port: "80"
|
||||
@@ -377,7 +358,7 @@ func formatIP(addr string) (addrIP string, ok bool) {
|
||||
// target: ":80" defaultPort: "443" returns host: "localhost", port: "80"
|
||||
func parseTarget(target, defaultPort string) (host, port string, err error) {
|
||||
if target == "" {
|
||||
return "", "", errMissingAddr
|
||||
return "", "", internal.ErrMissingAddr
|
||||
}
|
||||
if ip := net.ParseIP(target); ip != nil {
|
||||
// target is an IPv4 or IPv6(without brackets) address
|
||||
@@ -385,12 +366,14 @@ func parseTarget(target, defaultPort string) (host, port string, err error) {
|
||||
}
|
||||
if host, port, err = net.SplitHostPort(target); err == nil {
|
||||
if port == "" {
|
||||
// If the port field is empty (target ends with colon), e.g. "[::1]:", this is an error.
|
||||
return "", "", errEndsWithColon
|
||||
// If the port field is empty (target ends with colon), e.g. "[::1]:",
|
||||
// this is an error.
|
||||
return "", "", internal.ErrEndsWithColon
|
||||
}
|
||||
// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
|
||||
if host == "" {
|
||||
// Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
|
||||
// Keep consistent with net.Dial(): If the host is empty, as in ":80",
|
||||
// the local system is assumed.
|
||||
host = "localhost"
|
||||
}
|
||||
return host, port, nil
|
||||
|
70
vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go
generated
vendored
Normal file
70
vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package internal contains functionality internal to the dns resolver package.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NetResolver groups the methods on net.Resolver that are used by the DNS
|
||||
// resolver implementation. This allows the default net.Resolver instance to be
|
||||
// overidden from tests.
|
||||
type NetResolver interface {
|
||||
LookupHost(ctx context.Context, host string) (addrs []string, err error)
|
||||
LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
|
||||
LookupTXT(ctx context.Context, name string) (txts []string, err error)
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrMissingAddr is the error returned when building a DNS resolver when
|
||||
// the provided target name is empty.
|
||||
ErrMissingAddr = errors.New("dns resolver: missing address")
|
||||
|
||||
// ErrEndsWithColon is the error returned when building a DNS resolver when
|
||||
// the provided target name ends with a colon that is supposed to be the
|
||||
// separator between host and port. E.g. "::" is a valid address as it is
|
||||
// an IPv6 address (host only) and "[::]:" is invalid as it ends with a
|
||||
// colon as the host and port separator
|
||||
ErrEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
|
||||
)
|
||||
|
||||
// The following vars are overridden from tests.
|
||||
var (
|
||||
// MinResolutionRate is the minimum rate at which re-resolutions are
|
||||
// allowed. This helps to prevent excessive re-resolution.
|
||||
MinResolutionRate = 30 * time.Second
|
||||
|
||||
// TimeAfterFunc is used by the DNS resolver to wait for the given duration
|
||||
// to elapse. In non-test code, this is implemented by time.After. In test
|
||||
// code, this can be used to control the amount of time the resolver is
|
||||
// blocked waiting for the duration to elapse.
|
||||
TimeAfterFunc func(time.Duration) <-chan time.Time
|
||||
|
||||
// NewNetResolver returns the net.Resolver instance for the given target.
|
||||
NewNetResolver func(string) (NetResolver, error)
|
||||
|
||||
// AddressDialer is the dialer used to dial the DNS server. It accepts the
|
||||
// Host portion of the URL corresponding to the user's dial target and
|
||||
// returns a dial function.
|
||||
AddressDialer func(address string) func(context.Context, string, string) (net.Conn, error)
|
||||
)
|
11
vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go
generated
vendored
11
vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go
generated
vendored
@@ -20,13 +20,20 @@
|
||||
// name without scheme back to gRPC as resolved address.
|
||||
package passthrough
|
||||
|
||||
import "google.golang.org/grpc/resolver"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
const scheme = "passthrough"
|
||||
|
||||
type passthroughBuilder struct{}
|
||||
|
||||
func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
||||
if target.Endpoint() == "" && opts.Dialer == nil {
|
||||
return nil, errors.New("passthrough: received empty target in Build()")
|
||||
}
|
||||
r := &passthroughResolver{
|
||||
target: target,
|
||||
cc: cc,
|
||||
@@ -45,7 +52,7 @@ type passthroughResolver struct {
|
||||
}
|
||||
|
||||
func (r *passthroughResolver) start() {
|
||||
r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint}}})
|
||||
r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint()}}})
|
||||
}
|
||||
|
||||
func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOptions) {}
|
||||
|
4
vendor/google.golang.org/grpc/internal/resolver/unix/unix.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/resolver/unix/unix.go
generated
vendored
@@ -34,8 +34,8 @@ type builder struct {
|
||||
}
|
||||
|
||||
func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
|
||||
if target.Authority != "" {
|
||||
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority)
|
||||
if target.URL.Host != "" {
|
||||
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.URL.Host)
|
||||
}
|
||||
|
||||
// gRPC was parsing the dial target manually before PR #4817, and we
|
||||
|
130
vendor/google.golang.org/grpc/internal/serviceconfig/duration.go
generated
vendored
Normal file
130
vendor/google.golang.org/grpc/internal/serviceconfig/duration.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package serviceconfig
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Duration defines JSON marshal and unmarshal methods to conform to the
|
||||
// protobuf JSON spec defined [here].
|
||||
//
|
||||
// [here]: https://protobuf.dev/reference/protobuf/google.protobuf/#duration
|
||||
type Duration time.Duration
|
||||
|
||||
func (d Duration) String() string {
|
||||
return fmt.Sprint(time.Duration(d))
|
||||
}
|
||||
|
||||
// MarshalJSON converts from d to a JSON string output.
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
ns := time.Duration(d).Nanoseconds()
|
||||
sec := ns / int64(time.Second)
|
||||
ns = ns % int64(time.Second)
|
||||
|
||||
var sign string
|
||||
if sec < 0 || ns < 0 {
|
||||
sign, sec, ns = "-", -1*sec, -1*ns
|
||||
}
|
||||
|
||||
// Generated output always contains 0, 3, 6, or 9 fractional digits,
|
||||
// depending on required precision.
|
||||
str := fmt.Sprintf("%s%d.%09d", sign, sec, ns)
|
||||
str = strings.TrimSuffix(str, "000")
|
||||
str = strings.TrimSuffix(str, "000")
|
||||
str = strings.TrimSuffix(str, ".000")
|
||||
return []byte(fmt.Sprintf("\"%ss\"", str)), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals b as a duration JSON string into d.
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.HasSuffix(s, "s") {
|
||||
return fmt.Errorf("malformed duration %q: missing seconds unit", s)
|
||||
}
|
||||
neg := false
|
||||
if s[0] == '-' {
|
||||
neg = true
|
||||
s = s[1:]
|
||||
}
|
||||
ss := strings.SplitN(s[:len(s)-1], ".", 3)
|
||||
if len(ss) > 2 {
|
||||
return fmt.Errorf("malformed duration %q: too many decimals", s)
|
||||
}
|
||||
// hasDigits is set if either the whole or fractional part of the number is
|
||||
// present, since both are optional but one is required.
|
||||
hasDigits := false
|
||||
var sec, ns int64
|
||||
if len(ss[0]) > 0 {
|
||||
var err error
|
||||
if sec, err = strconv.ParseInt(ss[0], 10, 64); err != nil {
|
||||
return fmt.Errorf("malformed duration %q: %v", s, err)
|
||||
}
|
||||
// Maximum seconds value per the durationpb spec.
|
||||
const maxProtoSeconds = 315_576_000_000
|
||||
if sec > maxProtoSeconds {
|
||||
return fmt.Errorf("out of range: %q", s)
|
||||
}
|
||||
hasDigits = true
|
||||
}
|
||||
if len(ss) == 2 && len(ss[1]) > 0 {
|
||||
if len(ss[1]) > 9 {
|
||||
return fmt.Errorf("malformed duration %q: too many digits after decimal", s)
|
||||
}
|
||||
var err error
|
||||
if ns, err = strconv.ParseInt(ss[1], 10, 64); err != nil {
|
||||
return fmt.Errorf("malformed duration %q: %v", s, err)
|
||||
}
|
||||
for i := 9; i > len(ss[1]); i-- {
|
||||
ns *= 10
|
||||
}
|
||||
hasDigits = true
|
||||
}
|
||||
if !hasDigits {
|
||||
return fmt.Errorf("malformed duration %q: contains no numbers", s)
|
||||
}
|
||||
|
||||
if neg {
|
||||
sec *= -1
|
||||
ns *= -1
|
||||
}
|
||||
|
||||
// Maximum/minimum seconds/nanoseconds representable by Go's time.Duration.
|
||||
const maxSeconds = math.MaxInt64 / int64(time.Second)
|
||||
const maxNanosAtMaxSeconds = math.MaxInt64 % int64(time.Second)
|
||||
const minSeconds = math.MinInt64 / int64(time.Second)
|
||||
const minNanosAtMinSeconds = math.MinInt64 % int64(time.Second)
|
||||
|
||||
if sec > maxSeconds || (sec == maxSeconds && ns >= maxNanosAtMaxSeconds) {
|
||||
*d = Duration(math.MaxInt64)
|
||||
} else if sec < minSeconds || (sec == minSeconds && ns <= minNanosAtMinSeconds) {
|
||||
*d = Duration(math.MinInt64)
|
||||
} else {
|
||||
*d = Duration(sec*int64(time.Second) + ns)
|
||||
}
|
||||
return nil
|
||||
}
|
36
vendor/google.golang.org/grpc/internal/status/status.go
generated
vendored
36
vendor/google.golang.org/grpc/internal/status/status.go
generated
vendored
@@ -43,13 +43,41 @@ type Status struct {
|
||||
s *spb.Status
|
||||
}
|
||||
|
||||
// NewWithProto returns a new status including details from statusProto. This
|
||||
// is meant to be used by the gRPC library only.
|
||||
func NewWithProto(code codes.Code, message string, statusProto []string) *Status {
|
||||
if len(statusProto) != 1 {
|
||||
// No grpc-status-details bin header, or multiple; just ignore.
|
||||
return &Status{s: &spb.Status{Code: int32(code), Message: message}}
|
||||
}
|
||||
st := &spb.Status{}
|
||||
if err := proto.Unmarshal([]byte(statusProto[0]), st); err != nil {
|
||||
// Probably not a google.rpc.Status proto; do not provide details.
|
||||
return &Status{s: &spb.Status{Code: int32(code), Message: message}}
|
||||
}
|
||||
if st.Code == int32(code) {
|
||||
// The codes match between the grpc-status header and the
|
||||
// grpc-status-details-bin header; use the full details proto.
|
||||
return &Status{s: st}
|
||||
}
|
||||
return &Status{
|
||||
s: &spb.Status{
|
||||
Code: int32(codes.Internal),
|
||||
Message: fmt.Sprintf(
|
||||
"grpc-status-details-bin mismatch: grpc-status=%v, grpc-message=%q, grpc-status-details-bin=%+v",
|
||||
code, message, st,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a Status representing c and msg.
|
||||
func New(c codes.Code, msg string) *Status {
|
||||
return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
|
||||
}
|
||||
|
||||
// Newf returns New(c, fmt.Sprintf(format, a...)).
|
||||
func Newf(c codes.Code, format string, a ...interface{}) *Status {
|
||||
func Newf(c codes.Code, format string, a ...any) *Status {
|
||||
return New(c, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
@@ -64,7 +92,7 @@ func Err(c codes.Code, msg string) error {
|
||||
}
|
||||
|
||||
// Errorf returns Error(c, fmt.Sprintf(format, a...)).
|
||||
func Errorf(c codes.Code, format string, a ...interface{}) error {
|
||||
func Errorf(c codes.Code, format string, a ...any) error {
|
||||
return Err(c, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
@@ -120,11 +148,11 @@ func (s *Status) WithDetails(details ...proto.Message) (*Status, error) {
|
||||
|
||||
// Details returns a slice of details messages attached to the status.
|
||||
// If a detail cannot be decoded, the error is returned in place of the detail.
|
||||
func (s *Status) Details() []interface{} {
|
||||
func (s *Status) Details() []any {
|
||||
if s == nil || s.s == nil {
|
||||
return nil
|
||||
}
|
||||
details := make([]interface{}, 0, len(s.s.Details))
|
||||
details := make([]any, 0, len(s.s.Details))
|
||||
for _, any := range s.s.Details {
|
||||
detail := &ptypes.DynamicAny{}
|
||||
if err := ptypes.UnmarshalAny(any, detail); err != nil {
|
||||
|
29
vendor/google.golang.org/grpc/internal/tcp_keepalive_nonunix.go
generated
vendored
Normal file
29
vendor/google.golang.org/grpc/internal/tcp_keepalive_nonunix.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
//go:build !unix
|
||||
|
||||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// NetDialerWithTCPKeepalive returns a vanilla net.Dialer on non-unix platforms.
|
||||
func NetDialerWithTCPKeepalive() *net.Dialer {
|
||||
return &net.Dialer{}
|
||||
}
|
54
vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go
generated
vendored
Normal file
54
vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
//go:build unix
|
||||
|
||||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// NetDialerWithTCPKeepalive returns a net.Dialer that enables TCP keepalives on
|
||||
// the underlying connection with OS default values for keepalive parameters.
|
||||
//
|
||||
// TODO: Once https://github.com/golang/go/issues/62254 lands, and the
|
||||
// appropriate Go version becomes less than our least supported Go version, we
|
||||
// should look into using the new API to make things more straightforward.
|
||||
func NetDialerWithTCPKeepalive() *net.Dialer {
|
||||
return &net.Dialer{
|
||||
// Setting a negative value here prevents the Go stdlib from overriding
|
||||
// the values of TCP keepalive time and interval. It also prevents the
|
||||
// Go stdlib from enabling TCP keepalives by default.
|
||||
KeepAlive: time.Duration(-1),
|
||||
// This method is called after the underlying network socket is created,
|
||||
// but before dialing the socket (or calling its connect() method). The
|
||||
// combination of unconditionally enabling TCP keepalives here, and
|
||||
// disabling the overriding of TCP keepalive parameters by setting the
|
||||
// KeepAlive field to a negative value above, results in OS defaults for
|
||||
// the TCP keealive interval and time parameters.
|
||||
Control: func(_, _ string, c syscall.RawConn) error {
|
||||
return c.Control(func(fd uintptr) {
|
||||
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
143
vendor/google.golang.org/grpc/internal/transport/controlbuf.go
generated
vendored
143
vendor/google.golang.org/grpc/internal/transport/controlbuf.go
generated
vendored
@@ -22,6 +22,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
@@ -29,6 +30,7 @@ import (
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -38,7 +40,7 @@ var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
|
||||
}
|
||||
|
||||
type itemNode struct {
|
||||
it interface{}
|
||||
it any
|
||||
next *itemNode
|
||||
}
|
||||
|
||||
@@ -47,7 +49,7 @@ type itemList struct {
|
||||
tail *itemNode
|
||||
}
|
||||
|
||||
func (il *itemList) enqueue(i interface{}) {
|
||||
func (il *itemList) enqueue(i any) {
|
||||
n := &itemNode{it: i}
|
||||
if il.tail == nil {
|
||||
il.head, il.tail = n, n
|
||||
@@ -59,11 +61,11 @@ func (il *itemList) enqueue(i interface{}) {
|
||||
|
||||
// peek returns the first item in the list without removing it from the
|
||||
// list.
|
||||
func (il *itemList) peek() interface{} {
|
||||
func (il *itemList) peek() any {
|
||||
return il.head.it
|
||||
}
|
||||
|
||||
func (il *itemList) dequeue() interface{} {
|
||||
func (il *itemList) dequeue() any {
|
||||
if il.head == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -191,7 +193,7 @@ type goAway struct {
|
||||
code http2.ErrCode
|
||||
debugData []byte
|
||||
headsUp bool
|
||||
closeConn bool
|
||||
closeConn error // if set, loopyWriter will exit, resulting in conn closure
|
||||
}
|
||||
|
||||
func (*goAway) isTransportResponseFrame() bool { return false }
|
||||
@@ -209,6 +211,14 @@ type outFlowControlSizeRequest struct {
|
||||
|
||||
func (*outFlowControlSizeRequest) isTransportResponseFrame() bool { return false }
|
||||
|
||||
// closeConnection is an instruction to tell the loopy writer to flush the
|
||||
// framer and exit, which will cause the transport's connection to be closed
|
||||
// (by the client or server). The transport itself will close after the reader
|
||||
// encounters the EOF caused by the connection closure.
|
||||
type closeConnection struct{}
|
||||
|
||||
func (closeConnection) isTransportResponseFrame() bool { return false }
|
||||
|
||||
type outStreamState int
|
||||
|
||||
const (
|
||||
@@ -326,7 +336,7 @@ func (c *controlBuffer) put(it cbItem) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *controlBuffer) executeAndPut(f func(it interface{}) bool, it cbItem) (bool, error) {
|
||||
func (c *controlBuffer) executeAndPut(f func(it any) bool, it cbItem) (bool, error) {
|
||||
var wakeUp bool
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
@@ -363,7 +373,7 @@ func (c *controlBuffer) executeAndPut(f func(it interface{}) bool, it cbItem) (b
|
||||
}
|
||||
|
||||
// Note argument f should never be nil.
|
||||
func (c *controlBuffer) execute(f func(it interface{}) bool, it interface{}) (bool, error) {
|
||||
func (c *controlBuffer) execute(f func(it any) bool, it any) (bool, error) {
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
@@ -377,7 +387,7 @@ func (c *controlBuffer) execute(f func(it interface{}) bool, it interface{}) (bo
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *controlBuffer) get(block bool) (interface{}, error) {
|
||||
func (c *controlBuffer) get(block bool) (any, error) {
|
||||
for {
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
@@ -408,7 +418,7 @@ func (c *controlBuffer) get(block bool) (interface{}, error) {
|
||||
select {
|
||||
case <-c.ch:
|
||||
case <-c.done:
|
||||
return nil, ErrConnClosing
|
||||
return nil, errors.New("transport closed by client")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,12 +488,14 @@ type loopyWriter struct {
|
||||
hEnc *hpack.Encoder // HPACK encoder.
|
||||
bdpEst *bdpEstimator
|
||||
draining bool
|
||||
conn net.Conn
|
||||
logger *grpclog.PrefixLogger
|
||||
|
||||
// Side-specific handlers
|
||||
ssGoAwayHandler func(*goAway) (bool, error)
|
||||
}
|
||||
|
||||
func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator) *loopyWriter {
|
||||
func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn, logger *grpclog.PrefixLogger) *loopyWriter {
|
||||
var buf bytes.Buffer
|
||||
l := &loopyWriter{
|
||||
side: s,
|
||||
@@ -496,6 +508,8 @@ func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimato
|
||||
hBuf: &buf,
|
||||
hEnc: hpack.NewEncoder(&buf),
|
||||
bdpEst: bdpEst,
|
||||
conn: conn,
|
||||
logger: logger,
|
||||
}
|
||||
return l
|
||||
}
|
||||
@@ -513,23 +527,26 @@ const minBatchSize = 1000
|
||||
// 2. Stream level flow control quota available.
|
||||
//
|
||||
// In each iteration of run loop, other than processing the incoming control
|
||||
// frame, loopy calls processData, which processes one node from the activeStreams linked-list.
|
||||
// This results in writing of HTTP2 frames into an underlying write buffer.
|
||||
// When there's no more control frames to read from controlBuf, loopy flushes the write buffer.
|
||||
// As an optimization, to increase the batch size for each flush, loopy yields the processor, once
|
||||
// if the batch size is too low to give stream goroutines a chance to fill it up.
|
||||
// frame, loopy calls processData, which processes one node from the
|
||||
// activeStreams linked-list. This results in writing of HTTP2 frames into an
|
||||
// underlying write buffer. When there's no more control frames to read from
|
||||
// controlBuf, loopy flushes the write buffer. As an optimization, to increase
|
||||
// the batch size for each flush, loopy yields the processor, once if the batch
|
||||
// size is too low to give stream goroutines a chance to fill it up.
|
||||
//
|
||||
// Upon exiting, if the error causing the exit is not an I/O error, run()
|
||||
// flushes and closes the underlying connection. Otherwise, the connection is
|
||||
// left open to allow the I/O error to be encountered by the reader instead.
|
||||
func (l *loopyWriter) run() (err error) {
|
||||
defer func() {
|
||||
if err == ErrConnClosing {
|
||||
// Don't log ErrConnClosing as error since it happens
|
||||
// 1. When the connection is closed by some other known issue.
|
||||
// 2. User closed the connection.
|
||||
// 3. A graceful close of connection.
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("transport: loopyWriter.run returning. %v", err)
|
||||
}
|
||||
err = nil
|
||||
if l.logger.V(logLevel) {
|
||||
l.logger.Infof("loopyWriter exiting with error: %v", err)
|
||||
}
|
||||
if !isIOError(err) {
|
||||
l.framer.writer.Flush()
|
||||
l.conn.Close()
|
||||
}
|
||||
l.cbuf.finish()
|
||||
}()
|
||||
for {
|
||||
it, err := l.cbuf.get(true)
|
||||
@@ -574,7 +591,6 @@ func (l *loopyWriter) run() (err error) {
|
||||
}
|
||||
l.framer.writer.Flush()
|
||||
break hasdata
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -583,11 +599,11 @@ func (l *loopyWriter) outgoingWindowUpdateHandler(w *outgoingWindowUpdate) error
|
||||
return l.framer.fr.WriteWindowUpdate(w.streamID, w.increment)
|
||||
}
|
||||
|
||||
func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) error {
|
||||
func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) {
|
||||
// Otherwise update the quota.
|
||||
if w.streamID == 0 {
|
||||
l.sendQuota += w.increment
|
||||
return nil
|
||||
return
|
||||
}
|
||||
// Find the stream and update it.
|
||||
if str, ok := l.estdStreams[w.streamID]; ok {
|
||||
@@ -595,10 +611,9 @@ func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) error
|
||||
if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota > 0 && str.state == waitingOnStreamQuota {
|
||||
str.state = active
|
||||
l.activeStreams.enqueue(str)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) outgoingSettingsHandler(s *outgoingSettings) error {
|
||||
@@ -606,13 +621,11 @@ func (l *loopyWriter) outgoingSettingsHandler(s *outgoingSettings) error {
|
||||
}
|
||||
|
||||
func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
|
||||
if err := l.applySettings(s.ss); err != nil {
|
||||
return err
|
||||
}
|
||||
l.applySettings(s.ss)
|
||||
return l.framer.fr.WriteSettingsAck()
|
||||
}
|
||||
|
||||
func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
|
||||
func (l *loopyWriter) registerStreamHandler(h *registerStream) {
|
||||
str := &outStream{
|
||||
id: h.streamID,
|
||||
state: empty,
|
||||
@@ -620,15 +633,14 @@ func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
|
||||
wq: h.wq,
|
||||
}
|
||||
l.estdStreams[h.streamID] = str
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) headerHandler(h *headerFrame) error {
|
||||
if l.side == serverSide {
|
||||
str, ok := l.estdStreams[h.streamID]
|
||||
if !ok {
|
||||
if logger.V(logLevel) {
|
||||
logger.Warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
|
||||
if l.logger.V(logLevel) {
|
||||
l.logger.Infof("Unrecognized streamID %d in loopyWriter", h.streamID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -655,19 +667,20 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
|
||||
itl: &itemList{},
|
||||
wq: h.wq,
|
||||
}
|
||||
str.itl.enqueue(h)
|
||||
return l.originateStream(str)
|
||||
return l.originateStream(str, h)
|
||||
}
|
||||
|
||||
func (l *loopyWriter) originateStream(str *outStream) error {
|
||||
hdr := str.itl.dequeue().(*headerFrame)
|
||||
if err := hdr.initStream(str.id); err != nil {
|
||||
if err == ErrConnClosing {
|
||||
return err
|
||||
}
|
||||
// Other errors(errStreamDrain) need not close transport.
|
||||
func (l *loopyWriter) originateStream(str *outStream, hdr *headerFrame) error {
|
||||
// l.draining is set when handling GoAway. In which case, we want to avoid
|
||||
// creating new streams.
|
||||
if l.draining {
|
||||
// TODO: provide a better error with the reason we are in draining.
|
||||
hdr.onOrphaned(errStreamDrain)
|
||||
return nil
|
||||
}
|
||||
if err := hdr.initStream(str.id); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -682,8 +695,8 @@ func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.He
|
||||
l.hBuf.Reset()
|
||||
for _, f := range hf {
|
||||
if err := l.hEnc.WriteField(f); err != nil {
|
||||
if logger.V(logLevel) {
|
||||
logger.Warningf("transport: loopyWriter.writeHeader encountered error while encoding headers: %v", err)
|
||||
if l.logger.V(logLevel) {
|
||||
l.logger.Warningf("Encountered error while encoding headers: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -721,10 +734,10 @@ func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.He
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) preprocessData(df *dataFrame) error {
|
||||
func (l *loopyWriter) preprocessData(df *dataFrame) {
|
||||
str, ok := l.estdStreams[df.streamID]
|
||||
if !ok {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
// If we got data for a stream it means that
|
||||
// stream was originated and the headers were sent out.
|
||||
@@ -733,7 +746,6 @@ func (l *loopyWriter) preprocessData(df *dataFrame) error {
|
||||
str.state = active
|
||||
l.activeStreams.enqueue(str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) pingHandler(p *ping) error {
|
||||
@@ -744,9 +756,8 @@ func (l *loopyWriter) pingHandler(p *ping) error {
|
||||
|
||||
}
|
||||
|
||||
func (l *loopyWriter) outFlowControlSizeRequestHandler(o *outFlowControlSizeRequest) error {
|
||||
func (l *loopyWriter) outFlowControlSizeRequestHandler(o *outFlowControlSizeRequest) {
|
||||
o.resp <- l.sendQuota
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
|
||||
@@ -763,8 +774,9 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if l.side == clientSide && l.draining && len(l.estdStreams) == 0 {
|
||||
return ErrConnClosing
|
||||
if l.draining && len(l.estdStreams) == 0 {
|
||||
// Flush and close the connection; we are done with it.
|
||||
return errors.New("finished processing active streams while in draining mode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -799,7 +811,8 @@ func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
|
||||
if l.side == clientSide {
|
||||
l.draining = true
|
||||
if len(l.estdStreams) == 0 {
|
||||
return ErrConnClosing
|
||||
// Flush and close the connection; we are done with it.
|
||||
return errors.New("received GOAWAY with no active streams")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -817,10 +830,10 @@ func (l *loopyWriter) goAwayHandler(g *goAway) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) handle(i interface{}) error {
|
||||
func (l *loopyWriter) handle(i any) error {
|
||||
switch i := i.(type) {
|
||||
case *incomingWindowUpdate:
|
||||
return l.incomingWindowUpdateHandler(i)
|
||||
l.incomingWindowUpdateHandler(i)
|
||||
case *outgoingWindowUpdate:
|
||||
return l.outgoingWindowUpdateHandler(i)
|
||||
case *incomingSettings:
|
||||
@@ -830,7 +843,7 @@ func (l *loopyWriter) handle(i interface{}) error {
|
||||
case *headerFrame:
|
||||
return l.headerHandler(i)
|
||||
case *registerStream:
|
||||
return l.registerStreamHandler(i)
|
||||
l.registerStreamHandler(i)
|
||||
case *cleanupStream:
|
||||
return l.cleanupStreamHandler(i)
|
||||
case *earlyAbortStream:
|
||||
@@ -838,19 +851,24 @@ func (l *loopyWriter) handle(i interface{}) error {
|
||||
case *incomingGoAway:
|
||||
return l.incomingGoAwayHandler(i)
|
||||
case *dataFrame:
|
||||
return l.preprocessData(i)
|
||||
l.preprocessData(i)
|
||||
case *ping:
|
||||
return l.pingHandler(i)
|
||||
case *goAway:
|
||||
return l.goAwayHandler(i)
|
||||
case *outFlowControlSizeRequest:
|
||||
return l.outFlowControlSizeRequestHandler(i)
|
||||
l.outFlowControlSizeRequestHandler(i)
|
||||
case closeConnection:
|
||||
// Just return a non-I/O error and run() will flush and close the
|
||||
// connection.
|
||||
return ErrConnClosing
|
||||
default:
|
||||
return fmt.Errorf("transport: unknown control message type %T", i)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *loopyWriter) applySettings(ss []http2.Setting) error {
|
||||
func (l *loopyWriter) applySettings(ss []http2.Setting) {
|
||||
for _, s := range ss {
|
||||
switch s.ID {
|
||||
case http2.SettingInitialWindowSize:
|
||||
@@ -869,7 +887,6 @@ func (l *loopyWriter) applySettings(ss []http2.Setting) error {
|
||||
updateHeaderTblSize(l.hEnc, s.Val)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// processData removes the first stream from active streams, writes out at most 16KB
|
||||
@@ -903,7 +920,7 @@ func (l *loopyWriter) processData() (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
|
||||
return false, nil
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
l.activeStreams.enqueue(str)
|
||||
|
6
vendor/google.golang.org/grpc/internal/transport/defaults.go
generated
vendored
6
vendor/google.golang.org/grpc/internal/transport/defaults.go
generated
vendored
@@ -47,3 +47,9 @@ const (
|
||||
defaultClientMaxHeaderListSize = uint32(16 << 20)
|
||||
defaultServerMaxHeaderListSize = uint32(16 << 20)
|
||||
)
|
||||
|
||||
// MaxStreamID is the upper bound for the stream ID before the current
|
||||
// transport gracefully closes and new transport is created for subsequent RPCs.
|
||||
// This is set to 75% of 2^31-1. Streams are identified with an unsigned 31-bit
|
||||
// integer. It's exported so that tests can override it.
|
||||
var MaxStreamID = uint32(math.MaxInt32 * 3 / 4)
|
||||
|
130
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
130
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
@@ -39,6 +39,7 @@ import (
|
||||
"golang.org/x/net/http2"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
@@ -46,40 +47,65 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// NewServerHandlerTransport returns a ServerTransport handling gRPC
|
||||
// from inside an http.Handler. It requires that the http Server
|
||||
// supports HTTP/2.
|
||||
// NewServerHandlerTransport returns a ServerTransport handling gRPC from
|
||||
// inside an http.Handler, or writes an HTTP error to w and returns an error.
|
||||
// It requires that the http Server supports HTTP/2.
|
||||
func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []stats.Handler) (ServerTransport, error) {
|
||||
if r.ProtoMajor != 2 {
|
||||
return nil, errors.New("gRPC requires HTTP/2")
|
||||
msg := "gRPC requires HTTP/2"
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
if r.Method != "POST" {
|
||||
return nil, errors.New("invalid gRPC request method")
|
||||
msg := fmt.Sprintf("invalid gRPC request method %q", r.Method)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
// TODO: do we assume contentType is lowercase? we did before
|
||||
contentSubtype, validContentType := grpcutil.ContentSubtype(contentType)
|
||||
if !validContentType {
|
||||
return nil, errors.New("invalid gRPC request content-type")
|
||||
msg := fmt.Sprintf("invalid gRPC request content-type %q", contentType)
|
||||
http.Error(w, msg, http.StatusUnsupportedMediaType)
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
if _, ok := w.(http.Flusher); !ok {
|
||||
return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher")
|
||||
msg := "gRPC requires a ResponseWriter supporting http.Flusher"
|
||||
http.Error(w, msg, http.StatusInternalServerError)
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
|
||||
var localAddr net.Addr
|
||||
if la := r.Context().Value(http.LocalAddrContextKey); la != nil {
|
||||
localAddr, _ = la.(net.Addr)
|
||||
}
|
||||
var authInfo credentials.AuthInfo
|
||||
if r.TLS != nil {
|
||||
authInfo = credentials.TLSInfo{State: *r.TLS, CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}}
|
||||
}
|
||||
p := peer.Peer{
|
||||
Addr: strAddr(r.RemoteAddr),
|
||||
LocalAddr: localAddr,
|
||||
AuthInfo: authInfo,
|
||||
}
|
||||
st := &serverHandlerTransport{
|
||||
rw: w,
|
||||
req: r,
|
||||
closedCh: make(chan struct{}),
|
||||
writes: make(chan func()),
|
||||
peer: p,
|
||||
contentType: contentType,
|
||||
contentSubtype: contentSubtype,
|
||||
stats: stats,
|
||||
}
|
||||
st.logger = prefixLoggerForServerHandlerTransport(st)
|
||||
|
||||
if v := r.Header.Get("grpc-timeout"); v != "" {
|
||||
to, err := decodeTimeout(v)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
|
||||
msg := fmt.Sprintf("malformed grpc-timeout: %v", err)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
return nil, status.Error(codes.Internal, msg)
|
||||
}
|
||||
st.timeoutSet = true
|
||||
st.timeout = to
|
||||
@@ -97,7 +123,9 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s
|
||||
for _, v := range vv {
|
||||
v, err := decodeMetadataHeader(k, v)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "malformed binary metadata: %v", err)
|
||||
msg := fmt.Sprintf("malformed binary metadata %q in header %q: %v", v, k, err)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
return nil, status.Error(codes.Internal, msg)
|
||||
}
|
||||
metakv = append(metakv, k, v)
|
||||
}
|
||||
@@ -120,6 +148,8 @@ type serverHandlerTransport struct {
|
||||
|
||||
headerMD metadata.MD
|
||||
|
||||
peer peer.Peer
|
||||
|
||||
closeOnce sync.Once
|
||||
closedCh chan struct{} // closed on Close
|
||||
|
||||
@@ -138,16 +168,26 @@ type serverHandlerTransport struct {
|
||||
// TODO make sure this is consistent across handler_server and http2_server
|
||||
contentSubtype string
|
||||
|
||||
stats []stats.Handler
|
||||
stats []stats.Handler
|
||||
logger *grpclog.PrefixLogger
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) Close() {
|
||||
ht.closeOnce.Do(ht.closeCloseChanOnce)
|
||||
func (ht *serverHandlerTransport) Close(err error) {
|
||||
ht.closeOnce.Do(func() {
|
||||
if ht.logger.V(logLevel) {
|
||||
ht.logger.Infof("Closing: %v", err)
|
||||
}
|
||||
close(ht.closedCh)
|
||||
})
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) }
|
||||
|
||||
func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) }
|
||||
func (ht *serverHandlerTransport) Peer() *peer.Peer {
|
||||
return &peer.Peer{
|
||||
Addr: ht.peer.Addr,
|
||||
LocalAddr: ht.peer.LocalAddr,
|
||||
AuthInfo: ht.peer.AuthInfo,
|
||||
}
|
||||
}
|
||||
|
||||
// strAddr is a net.Addr backed by either a TCP "ip:port" string, or
|
||||
// the empty string if unknown.
|
||||
@@ -202,18 +242,20 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
|
||||
h.Set("Grpc-Message", encodeGrpcMessage(m))
|
||||
}
|
||||
|
||||
s.hdrMu.Lock()
|
||||
if p := st.Proto(); p != nil && len(p.Details) > 0 {
|
||||
delete(s.trailer, grpcStatusDetailsBinHeader)
|
||||
stBytes, err := proto.Marshal(p)
|
||||
if err != nil {
|
||||
// TODO: return error instead, when callers are able to handle it.
|
||||
panic(err)
|
||||
}
|
||||
|
||||
h.Set("Grpc-Status-Details-Bin", encodeBinHeader(stBytes))
|
||||
h.Set(grpcStatusDetailsBinHeader, encodeBinHeader(stBytes))
|
||||
}
|
||||
|
||||
if md := s.Trailer(); len(md) > 0 {
|
||||
for k, vv := range md {
|
||||
if len(s.trailer) > 0 {
|
||||
for k, vv := range s.trailer {
|
||||
// Clients don't tolerate reading restricted headers after some non restricted ones were sent.
|
||||
if isReservedHeader(k) {
|
||||
continue
|
||||
@@ -225,6 +267,7 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
|
||||
}
|
||||
}
|
||||
}
|
||||
s.hdrMu.Unlock()
|
||||
})
|
||||
|
||||
if err == nil { // transport has not been closed
|
||||
@@ -236,7 +279,7 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
|
||||
})
|
||||
}
|
||||
}
|
||||
ht.Close()
|
||||
ht.Close(errors.New("finished writing status"))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -269,7 +312,7 @@ func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
|
||||
}
|
||||
|
||||
// writeCustomHeaders sets custom headers set on the stream via SetHeader
|
||||
// on the first write call (Write, WriteHeader, or WriteStatus).
|
||||
// on the first write call (Write, WriteHeader, or WriteStatus)
|
||||
func (ht *serverHandlerTransport) writeCustomHeaders(s *Stream) {
|
||||
h := ht.rw.Header()
|
||||
|
||||
@@ -326,10 +369,8 @@ func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
|
||||
func (ht *serverHandlerTransport) HandleStreams(ctx context.Context, startStream func(*Stream)) {
|
||||
// With this transport type there will be exactly 1 stream: this HTTP request.
|
||||
|
||||
ctx := ht.req.Context()
|
||||
var cancel context.CancelFunc
|
||||
if ht.timeoutSet {
|
||||
ctx, cancel = context.WithTimeout(ctx, ht.timeout)
|
||||
@@ -346,37 +387,22 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace
|
||||
case <-ht.req.Context().Done():
|
||||
}
|
||||
cancel()
|
||||
ht.Close()
|
||||
ht.Close(errors.New("request is done processing"))
|
||||
}()
|
||||
|
||||
req := ht.req
|
||||
|
||||
s := &Stream{
|
||||
id: 0, // irrelevant
|
||||
requestRead: func(int) {},
|
||||
cancel: cancel,
|
||||
buf: newRecvBuffer(),
|
||||
st: ht,
|
||||
method: req.URL.Path,
|
||||
recvCompress: req.Header.Get("grpc-encoding"),
|
||||
contentSubtype: ht.contentSubtype,
|
||||
}
|
||||
pr := &peer.Peer{
|
||||
Addr: ht.RemoteAddr(),
|
||||
}
|
||||
if req.TLS != nil {
|
||||
pr.AuthInfo = credentials.TLSInfo{State: *req.TLS, CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}}
|
||||
}
|
||||
ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
|
||||
s.ctx = peer.NewContext(ctx, pr)
|
||||
for _, sh := range ht.stats {
|
||||
s.ctx = sh.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
|
||||
inHeader := &stats.InHeader{
|
||||
FullMethod: s.method,
|
||||
RemoteAddr: ht.RemoteAddr(),
|
||||
Compression: s.recvCompress,
|
||||
}
|
||||
sh.HandleRPC(s.ctx, inHeader)
|
||||
req := ht.req
|
||||
s := &Stream{
|
||||
id: 0, // irrelevant
|
||||
ctx: ctx,
|
||||
requestRead: func(int) {},
|
||||
cancel: cancel,
|
||||
buf: newRecvBuffer(),
|
||||
st: ht,
|
||||
method: req.URL.Path,
|
||||
recvCompress: req.Header.Get("grpc-encoding"),
|
||||
contentSubtype: ht.contentSubtype,
|
||||
headerWireLength: 0, // won't have access to header wire length until golang/go#18997.
|
||||
}
|
||||
s.trReader = &transportReader{
|
||||
reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf, freeBuffer: func(*bytes.Buffer) {}},
|
||||
@@ -435,7 +461,7 @@ func (ht *serverHandlerTransport) IncrMsgSent() {}
|
||||
|
||||
func (ht *serverHandlerTransport) IncrMsgRecv() {}
|
||||
|
||||
func (ht *serverHandlerTransport) Drain() {
|
||||
func (ht *serverHandlerTransport) Drain(debugData string) {
|
||||
panic("Drain() is not implemented")
|
||||
}
|
||||
|
||||
|
192
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
192
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
@@ -36,13 +36,15 @@ import (
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
icredentials "google.golang.org/grpc/internal/credentials"
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
imetadata "google.golang.org/grpc/internal/metadata"
|
||||
istatus "google.golang.org/grpc/internal/status"
|
||||
"google.golang.org/grpc/internal/syscall"
|
||||
isyscall "google.golang.org/grpc/internal/syscall"
|
||||
"google.golang.org/grpc/internal/transport/networktype"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
@@ -59,11 +61,15 @@ var clientConnectionCounter uint64
|
||||
|
||||
// http2Client implements the ClientTransport interface with HTTP2.
|
||||
type http2Client struct {
|
||||
lastRead int64 // Keep this field 64-bit aligned. Accessed atomically.
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
ctxDone <-chan struct{} // Cache the ctx.Done() chan.
|
||||
userAgent string
|
||||
lastRead int64 // Keep this field 64-bit aligned. Accessed atomically.
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
ctxDone <-chan struct{} // Cache the ctx.Done() chan.
|
||||
userAgent string
|
||||
// address contains the resolver returned address for this transport.
|
||||
// If the `ServerName` field is set, it takes precedence over `CallHdr.Host`
|
||||
// passed to `NewStream`, when determining the :authority header.
|
||||
address resolver.Address
|
||||
md metadata.MD
|
||||
conn net.Conn // underlying communication channel
|
||||
loopy *loopyWriter
|
||||
@@ -136,12 +142,12 @@ type http2Client struct {
|
||||
channelzID *channelz.Identifier
|
||||
czData *channelzData
|
||||
|
||||
onGoAway func(GoAwayReason)
|
||||
onClose func()
|
||||
onClose func(GoAwayReason)
|
||||
|
||||
bufferPool *bufferPool
|
||||
|
||||
connectionID uint64
|
||||
logger *grpclog.PrefixLogger
|
||||
}
|
||||
|
||||
func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr resolver.Address, useProxy bool, grpcUA string) (net.Conn, error) {
|
||||
@@ -171,7 +177,7 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
|
||||
if networkType == "tcp" && useProxy {
|
||||
return proxyDial(ctx, address, grpcUA)
|
||||
}
|
||||
return (&net.Dialer{}).DialContext(ctx, networkType, address)
|
||||
return internal.NetDialerWithTCPKeepalive().DialContext(ctx, networkType, address)
|
||||
}
|
||||
|
||||
func isTemporary(err error) bool {
|
||||
@@ -193,7 +199,7 @@ func isTemporary(err error) bool {
|
||||
// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2
|
||||
// and starts to receive messages on it. Non-nil error returns if construction
|
||||
// fails.
|
||||
func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onGoAway func(GoAwayReason), onClose func()) (_ *http2Client, err error) {
|
||||
func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onClose func(GoAwayReason)) (_ *http2Client, err error) {
|
||||
scheme := "http"
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer func() {
|
||||
@@ -213,7 +219,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
if opts.FailOnNonTempDialError {
|
||||
return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
|
||||
}
|
||||
return nil, connectionErrorf(true, err, "transport: Error while dialing %v", err)
|
||||
return nil, connectionErrorf(true, err, "transport: Error while dialing: %v", err)
|
||||
}
|
||||
|
||||
// Any further errors will close the underlying connection
|
||||
@@ -238,8 +244,11 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
go func(conn net.Conn) {
|
||||
defer ctxMonitorDone.Fire() // Signal this goroutine has exited.
|
||||
<-newClientCtx.Done() // Block until connectCtx expires or the defer above executes.
|
||||
if connectCtx.Err() != nil {
|
||||
if err := connectCtx.Err(); err != nil {
|
||||
// connectCtx expired before exiting the function. Hard close the connection.
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("Aborting due to connect deadline expiring: %v", err)
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
}(conn)
|
||||
@@ -254,7 +263,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
}
|
||||
keepaliveEnabled := false
|
||||
if kp.Time != infinity {
|
||||
if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
|
||||
if err = isyscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
|
||||
return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
|
||||
}
|
||||
keepaliveEnabled = true
|
||||
@@ -314,6 +323,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
cancel: cancel,
|
||||
userAgent: opts.UserAgent,
|
||||
registeredCompressors: grpcutil.RegisteredCompressors(),
|
||||
address: addr,
|
||||
conn: conn,
|
||||
remoteAddr: conn.RemoteAddr(),
|
||||
localAddr: conn.LocalAddr(),
|
||||
@@ -321,7 +331,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
readerDone: make(chan struct{}),
|
||||
writerDone: make(chan struct{}),
|
||||
goAway: make(chan struct{}),
|
||||
framer: newFramer(conn, writeBufSize, readBufSize, maxHeaderListSize),
|
||||
framer: newFramer(conn, writeBufSize, readBufSize, opts.SharedWriteBuffer, maxHeaderListSize),
|
||||
fc: &trInFlow{limit: uint32(icwz)},
|
||||
scheme: scheme,
|
||||
activeStreams: make(map[uint32]*Stream),
|
||||
@@ -335,11 +345,11 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
streamQuota: defaultMaxStreamsClient,
|
||||
streamsQuotaAvailable: make(chan struct{}, 1),
|
||||
czData: new(channelzData),
|
||||
onGoAway: onGoAway,
|
||||
keepaliveEnabled: keepaliveEnabled,
|
||||
bufferPool: newBufferPool(),
|
||||
onClose: onClose,
|
||||
}
|
||||
t.logger = prefixLoggerForClientTransport(t)
|
||||
// Add peer information to the http2client context.
|
||||
t.ctx = peer.NewContext(t.ctx, t.getPeer())
|
||||
|
||||
@@ -438,17 +448,8 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||
return nil, err
|
||||
}
|
||||
go func() {
|
||||
t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst)
|
||||
err := t.loopy.run()
|
||||
if err != nil {
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: loopyWriter.run returning. Err: %v", err)
|
||||
}
|
||||
}
|
||||
// Do not close the transport. Let reader goroutine handle it since
|
||||
// there might be data in the buffers.
|
||||
t.conn.Close()
|
||||
t.controlBuf.finish()
|
||||
t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger)
|
||||
t.loopy.run()
|
||||
close(t.writerDone)
|
||||
}()
|
||||
return t, nil
|
||||
@@ -493,8 +494,9 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
|
||||
|
||||
func (t *http2Client) getPeer() *peer.Peer {
|
||||
return &peer.Peer{
|
||||
Addr: t.remoteAddr,
|
||||
AuthInfo: t.authInfo, // Can be nil
|
||||
Addr: t.remoteAddr,
|
||||
AuthInfo: t.authInfo, // Can be nil
|
||||
LocalAddr: t.localAddr,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,6 +704,18 @@ func (e NewStreamError) Error() string {
|
||||
// streams. All non-nil errors returned will be *NewStreamError.
|
||||
func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) {
|
||||
ctx = peer.NewContext(ctx, t.getPeer())
|
||||
|
||||
// ServerName field of the resolver returned address takes precedence over
|
||||
// Host field of CallHdr to determine the :authority header. This is because,
|
||||
// the ServerName field takes precedence for server authentication during
|
||||
// TLS handshake, and the :authority header should match the value used
|
||||
// for server authentication.
|
||||
if t.address.ServerName != "" {
|
||||
newCallHdr := *callHdr
|
||||
newCallHdr.Host = t.address.ServerName
|
||||
callHdr = &newCallHdr
|
||||
}
|
||||
|
||||
headerFields, err := t.createHeaderFields(ctx, callHdr)
|
||||
if err != nil {
|
||||
return nil, &NewStreamError{Err: err, AllowTransparentRetry: false}
|
||||
@@ -726,15 +740,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
|
||||
endStream: false,
|
||||
initStream: func(id uint32) error {
|
||||
t.mu.Lock()
|
||||
if state := t.state; state != reachable {
|
||||
// TODO: handle transport closure in loopy instead and remove this
|
||||
// initStream is never called when transport is draining.
|
||||
if t.state == closing {
|
||||
t.mu.Unlock()
|
||||
// Do a quick cleanup.
|
||||
err := error(errStreamDrain)
|
||||
if state == closing {
|
||||
err = ErrConnClosing
|
||||
}
|
||||
cleanup(err)
|
||||
return err
|
||||
cleanup(ErrConnClosing)
|
||||
return ErrConnClosing
|
||||
}
|
||||
if channelz.IsOn() {
|
||||
atomic.AddInt64(&t.czData.streamsStarted, 1)
|
||||
@@ -752,7 +763,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
|
||||
}
|
||||
firstTry := true
|
||||
var ch chan struct{}
|
||||
checkForStreamQuota := func(it interface{}) bool {
|
||||
transportDrainRequired := false
|
||||
checkForStreamQuota := func(it any) bool {
|
||||
if t.streamQuota <= 0 { // Can go negative if server decreases it.
|
||||
if firstTry {
|
||||
t.waitingStreams++
|
||||
@@ -767,10 +779,15 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
|
||||
h := it.(*headerFrame)
|
||||
h.streamID = t.nextID
|
||||
t.nextID += 2
|
||||
|
||||
// Drain client transport if nextID > MaxStreamID which signals gRPC that
|
||||
// the connection is closed and a new one must be created for subsequent RPCs.
|
||||
transportDrainRequired = t.nextID > MaxStreamID
|
||||
|
||||
s.id = h.streamID
|
||||
s.fc = &inFlow{limit: uint32(t.initialWindowSize)}
|
||||
t.mu.Lock()
|
||||
if t.activeStreams == nil { // Can be niled from Close().
|
||||
if t.state == draining || t.activeStreams == nil { // Can be niled from Close().
|
||||
t.mu.Unlock()
|
||||
return false // Don't create a stream if the transport is already closed.
|
||||
}
|
||||
@@ -785,7 +802,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
|
||||
return true
|
||||
}
|
||||
var hdrListSizeErr error
|
||||
checkForHeaderListSize := func(it interface{}) bool {
|
||||
checkForHeaderListSize := func(it any) bool {
|
||||
if t.maxSendHeaderListSize == nil {
|
||||
return true
|
||||
}
|
||||
@@ -800,7 +817,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
|
||||
return true
|
||||
}
|
||||
for {
|
||||
success, err := t.controlBuf.executeAndPut(func(it interface{}) bool {
|
||||
success, err := t.controlBuf.executeAndPut(func(it any) bool {
|
||||
return checkForHeaderListSize(it) && checkForStreamQuota(it)
|
||||
}, hdr)
|
||||
if err != nil {
|
||||
@@ -846,6 +863,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
|
||||
sh.HandleRPC(s.ctx, outHeader)
|
||||
}
|
||||
}
|
||||
if transportDrainRequired {
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Draining transport: t.nextID > MaxStreamID")
|
||||
}
|
||||
t.GracefulClose()
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -906,7 +929,7 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.
|
||||
rst: rst,
|
||||
rstCode: rstCode,
|
||||
}
|
||||
addBackStreamQuota := func(interface{}) bool {
|
||||
addBackStreamQuota := func(any) bool {
|
||||
t.streamQuota++
|
||||
if t.streamQuota > 0 && t.waitingStreams > 0 {
|
||||
select {
|
||||
@@ -934,9 +957,14 @@ func (t *http2Client) Close(err error) {
|
||||
t.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Closing: %v", err)
|
||||
}
|
||||
// Call t.onClose ASAP to prevent the client from attempting to create new
|
||||
// streams.
|
||||
t.onClose()
|
||||
if t.state != draining {
|
||||
t.onClose(GoAwayInvalid)
|
||||
}
|
||||
t.state = closing
|
||||
streams := t.activeStreams
|
||||
t.activeStreams = nil
|
||||
@@ -986,11 +1014,15 @@ func (t *http2Client) GracefulClose() {
|
||||
t.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("GracefulClose called")
|
||||
}
|
||||
t.onClose(GoAwayInvalid)
|
||||
t.state = draining
|
||||
active := len(t.activeStreams)
|
||||
t.mu.Unlock()
|
||||
if active == 0 {
|
||||
t.Close(ErrConnClosing)
|
||||
t.Close(connectionErrorf(true, nil, "no active streams left to process while draining"))
|
||||
return
|
||||
}
|
||||
t.controlBuf.put(&incomingGoAway{})
|
||||
@@ -1050,7 +1082,7 @@ func (t *http2Client) updateWindow(s *Stream, n uint32) {
|
||||
// for the transport and the stream based on the current bdp
|
||||
// estimation.
|
||||
func (t *http2Client) updateFlowControl(n uint32) {
|
||||
updateIWS := func(interface{}) bool {
|
||||
updateIWS := func(any) bool {
|
||||
t.initialWindowSize = int32(n)
|
||||
t.mu.Lock()
|
||||
for _, s := range t.activeStreams {
|
||||
@@ -1147,8 +1179,8 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
|
||||
}
|
||||
statusCode, ok := http2ErrConvTab[f.ErrCode]
|
||||
if !ok {
|
||||
if logger.V(logLevel) {
|
||||
logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error %v", f.ErrCode)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Received a RST_STREAM frame with code %q, but found no mapped gRPC status", f.ErrCode)
|
||||
}
|
||||
statusCode = codes.Unknown
|
||||
}
|
||||
@@ -1203,7 +1235,7 @@ func (t *http2Client) handleSettings(f *http2.SettingsFrame, isFirst bool) {
|
||||
}
|
||||
updateFuncs = append(updateFuncs, updateStreamQuota)
|
||||
}
|
||||
t.controlBuf.executeAndPut(func(interface{}) bool {
|
||||
t.controlBuf.executeAndPut(func(any) bool {
|
||||
for _, f := range updateFuncs {
|
||||
f()
|
||||
}
|
||||
@@ -1230,10 +1262,12 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
||||
t.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if f.ErrCode == http2.ErrCodeEnhanceYourCalm {
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("Client received GoAway with http2.ErrCodeEnhanceYourCalm.")
|
||||
}
|
||||
if f.ErrCode == http2.ErrCodeEnhanceYourCalm && string(f.DebugData()) == "too_many_pings" {
|
||||
// When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug
|
||||
// data equal to ASCII "too_many_pings", it should log the occurrence at a log level that is
|
||||
// enabled by default and double the configure KEEPALIVE_TIME used for new connections
|
||||
// on that channel.
|
||||
logger.Errorf("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\".")
|
||||
}
|
||||
id := f.LastStreamID
|
||||
if id > 0 && id%2 == 0 {
|
||||
@@ -1266,8 +1300,10 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
||||
// Notify the clientconn about the GOAWAY before we set the state to
|
||||
// draining, to allow the client to stop attempting to create streams
|
||||
// before disallowing new streams on this connection.
|
||||
t.onGoAway(t.goAwayReason)
|
||||
t.state = draining
|
||||
if t.state != draining {
|
||||
t.onClose(t.goAwayReason)
|
||||
t.state = draining
|
||||
}
|
||||
}
|
||||
// All streams with IDs greater than the GoAwayId
|
||||
// and smaller than the previous GoAway ID should be killed.
|
||||
@@ -1303,7 +1339,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
||||
|
||||
// setGoAwayReason sets the value of t.goAwayReason based
|
||||
// on the GoAway frame received.
|
||||
// It expects a lock on transport's mutext to be held by
|
||||
// It expects a lock on transport's mutex to be held by
|
||||
// the caller.
|
||||
func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
|
||||
t.goAwayReason = GoAwayNoReason
|
||||
@@ -1365,7 +1401,6 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||
mdata = make(map[string][]string)
|
||||
contentTypeErr = "malformed header: missing HTTP content-type"
|
||||
grpcMessage string
|
||||
statusGen *status.Status
|
||||
recvCompress string
|
||||
httpStatusCode *int
|
||||
httpStatusErr string
|
||||
@@ -1400,12 +1435,6 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||
rawStatusCode = codes.Code(uint32(code))
|
||||
case "grpc-message":
|
||||
grpcMessage = decodeGrpcMessage(hf.Value)
|
||||
case "grpc-status-details-bin":
|
||||
var err error
|
||||
statusGen, err = decodeGRPCStatusDetails(hf.Value)
|
||||
if err != nil {
|
||||
headerError = fmt.Sprintf("transport: malformed grpc-status-details-bin: %v", err)
|
||||
}
|
||||
case ":status":
|
||||
if hf.Value == "200" {
|
||||
httpStatusErr = ""
|
||||
@@ -1471,14 +1500,15 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||
return
|
||||
}
|
||||
|
||||
isHeader := false
|
||||
|
||||
// If headerChan hasn't been closed yet
|
||||
if atomic.CompareAndSwapUint32(&s.headerChanClosed, 0, 1) {
|
||||
s.headerValid = true
|
||||
if !endStream {
|
||||
// HEADERS frame block carries a Response-Headers.
|
||||
isHeader = true
|
||||
// For headers, set them in s.header and close headerChan. For trailers or
|
||||
// trailers-only, closeStream will set the trailers and close headerChan as
|
||||
// needed.
|
||||
if !endStream {
|
||||
// If headerChan hasn't been closed yet (expected, given we checked it
|
||||
// above, but something else could have potentially closed the whole
|
||||
// stream).
|
||||
if atomic.CompareAndSwapUint32(&s.headerChanClosed, 0, 1) {
|
||||
s.headerValid = true
|
||||
// These values can be set without any synchronization because
|
||||
// stream goroutine will read it only after seeing a closed
|
||||
// headerChan which we'll close after setting this.
|
||||
@@ -1486,15 +1516,12 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||
if len(mdata) > 0 {
|
||||
s.header = mdata
|
||||
}
|
||||
} else {
|
||||
// HEADERS frame block carries a Trailers-Only.
|
||||
s.noHeaders = true
|
||||
close(s.headerChan)
|
||||
}
|
||||
close(s.headerChan)
|
||||
}
|
||||
|
||||
for _, sh := range t.statsHandlers {
|
||||
if isHeader {
|
||||
if !endStream {
|
||||
inHeader := &stats.InHeader{
|
||||
Client: true,
|
||||
WireLength: int(frame.Header().Length),
|
||||
@@ -1516,13 +1543,12 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
||||
return
|
||||
}
|
||||
|
||||
if statusGen == nil {
|
||||
statusGen = status.New(rawStatusCode, grpcMessage)
|
||||
}
|
||||
status := istatus.NewWithProto(rawStatusCode, grpcMessage, mdata[grpcStatusDetailsBinHeader])
|
||||
|
||||
// if client received END_STREAM from server while stream was still active, send RST_STREAM
|
||||
rst := s.getState() == streamActive
|
||||
t.closeStream(s, io.EOF, rst, http2.ErrCodeNo, statusGen, mdata, true)
|
||||
// If client received END_STREAM from server while stream was still active,
|
||||
// send RST_STREAM.
|
||||
rstStream := s.getState() == streamActive
|
||||
t.closeStream(s, io.EOF, rstStream, http2.ErrCodeNo, status, mdata, true)
|
||||
}
|
||||
|
||||
// readServerPreface reads and handles the initial settings frame from the
|
||||
@@ -1756,3 +1782,9 @@ func (t *http2Client) getOutFlowWindow() int64 {
|
||||
return -2
|
||||
}
|
||||
}
|
||||
|
||||
func (t *http2Client) stateForTesting() transportState {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.state
|
||||
}
|
||||
|
346
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
346
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
@@ -21,6 +21,7 @@ package transport
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
@@ -34,13 +35,16 @@ import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/internal/syscall"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
@@ -64,18 +68,15 @@ var serverConnectionCounter uint64
|
||||
|
||||
// http2Server implements the ServerTransport interface with HTTP2.
|
||||
type http2Server struct {
|
||||
lastRead int64 // Keep this field 64-bit aligned. Accessed atomically.
|
||||
ctx context.Context
|
||||
done chan struct{}
|
||||
conn net.Conn
|
||||
loopy *loopyWriter
|
||||
readerDone chan struct{} // sync point to enable testing.
|
||||
writerDone chan struct{} // sync point to enable testing.
|
||||
remoteAddr net.Addr
|
||||
localAddr net.Addr
|
||||
authInfo credentials.AuthInfo // auth info about the connection
|
||||
inTapHandle tap.ServerInHandle
|
||||
framer *framer
|
||||
lastRead int64 // Keep this field 64-bit aligned. Accessed atomically.
|
||||
done chan struct{}
|
||||
conn net.Conn
|
||||
loopy *loopyWriter
|
||||
readerDone chan struct{} // sync point to enable testing.
|
||||
loopyWriterDone chan struct{}
|
||||
peer peer.Peer
|
||||
inTapHandle tap.ServerInHandle
|
||||
framer *framer
|
||||
// The max number of concurrent streams.
|
||||
maxStreams uint32
|
||||
// controlBuf delivers all the control related tasks (e.g., window
|
||||
@@ -101,13 +102,13 @@ type http2Server struct {
|
||||
|
||||
mu sync.Mutex // guard the following
|
||||
|
||||
// drainChan is initialized when Drain() is called the first time.
|
||||
// After which the server writes out the first GoAway(with ID 2^31-1) frame.
|
||||
// Then an independent goroutine will be launched to later send the second GoAway.
|
||||
// During this time we don't want to write another first GoAway(with ID 2^31 -1) frame.
|
||||
// Thus call to Drain() will be a no-op if drainChan is already initialized since draining is
|
||||
// already underway.
|
||||
drainChan chan struct{}
|
||||
// drainEvent is initialized when Drain() is called the first time. After
|
||||
// which the server writes out the first GoAway(with ID 2^31-1) frame. Then
|
||||
// an independent goroutine will be launched to later send the second
|
||||
// GoAway. During this time we don't want to write another first GoAway(with
|
||||
// ID 2^31 -1) frame. Thus call to Drain() will be a no-op if drainEvent is
|
||||
// already initialized since draining is already underway.
|
||||
drainEvent *grpcsync.Event
|
||||
state transportState
|
||||
activeStreams map[uint32]*Stream
|
||||
// idle is the time instant when the connection went idle.
|
||||
@@ -127,6 +128,8 @@ type http2Server struct {
|
||||
// This lock may not be taken if mu is already held.
|
||||
maxStreamMu sync.Mutex
|
||||
maxStreamID uint32 // max stream ID ever seen
|
||||
|
||||
logger *grpclog.PrefixLogger
|
||||
}
|
||||
|
||||
// NewServerTransport creates a http2 transport with conn and configuration
|
||||
@@ -159,21 +162,16 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
if config.MaxHeaderListSize != nil {
|
||||
maxHeaderListSize = *config.MaxHeaderListSize
|
||||
}
|
||||
framer := newFramer(conn, writeBufSize, readBufSize, maxHeaderListSize)
|
||||
framer := newFramer(conn, writeBufSize, readBufSize, config.SharedWriteBuffer, maxHeaderListSize)
|
||||
// Send initial settings as connection preface to client.
|
||||
isettings := []http2.Setting{{
|
||||
ID: http2.SettingMaxFrameSize,
|
||||
Val: http2MaxFrameLen,
|
||||
}}
|
||||
// TODO(zhaoq): Have a better way to signal "no limit" because 0 is
|
||||
// permitted in the HTTP2 spec.
|
||||
maxStreams := config.MaxStreams
|
||||
if maxStreams == 0 {
|
||||
maxStreams = math.MaxUint32
|
||||
} else {
|
||||
if config.MaxStreams != math.MaxUint32 {
|
||||
isettings = append(isettings, http2.Setting{
|
||||
ID: http2.SettingMaxConcurrentStreams,
|
||||
Val: maxStreams,
|
||||
Val: config.MaxStreams,
|
||||
})
|
||||
}
|
||||
dynamicWindow := true
|
||||
@@ -232,7 +230,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
kp.Timeout = defaultServerKeepaliveTimeout
|
||||
}
|
||||
if kp.Time != infinity {
|
||||
if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
|
||||
if err = syscall.SetTCPUserTimeout(rawConn, kp.Timeout); err != nil {
|
||||
return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -242,17 +240,19 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
peer := peer.Peer{
|
||||
Addr: conn.RemoteAddr(),
|
||||
LocalAddr: conn.LocalAddr(),
|
||||
AuthInfo: authInfo,
|
||||
}
|
||||
t := &http2Server{
|
||||
ctx: setConnection(context.Background(), rawConn),
|
||||
done: done,
|
||||
conn: conn,
|
||||
remoteAddr: conn.RemoteAddr(),
|
||||
localAddr: conn.LocalAddr(),
|
||||
authInfo: authInfo,
|
||||
peer: peer,
|
||||
framer: framer,
|
||||
readerDone: make(chan struct{}),
|
||||
writerDone: make(chan struct{}),
|
||||
maxStreams: maxStreams,
|
||||
loopyWriterDone: make(chan struct{}),
|
||||
maxStreams: config.MaxStreams,
|
||||
inTapHandle: config.InTapHandle,
|
||||
fc: &trInFlow{limit: uint32(icwz)},
|
||||
state: reachable,
|
||||
@@ -265,8 +265,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
czData: new(channelzData),
|
||||
bufferPool: newBufferPool(),
|
||||
}
|
||||
// Add peer information to the http2server context.
|
||||
t.ctx = peer.NewContext(t.ctx, t.getPeer())
|
||||
t.logger = prefixLoggerForServerTransport(t)
|
||||
|
||||
t.controlBuf = newControlBuffer(t.done)
|
||||
if dynamicWindow {
|
||||
@@ -275,15 +274,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
updateFlowControl: t.updateFlowControl,
|
||||
}
|
||||
}
|
||||
for _, sh := range t.stats {
|
||||
t.ctx = sh.TagConn(t.ctx, &stats.ConnTagInfo{
|
||||
RemoteAddr: t.remoteAddr,
|
||||
LocalAddr: t.localAddr,
|
||||
})
|
||||
connBegin := &stats.ConnBegin{}
|
||||
sh.HandleConn(t.ctx, connBegin)
|
||||
}
|
||||
t.channelzID, err = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr))
|
||||
t.channelzID, err = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.peer.Addr, t.peer.LocalAddr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -293,7 +284,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
t.Close()
|
||||
t.Close(err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -329,23 +320,18 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||
t.handleSettings(sf)
|
||||
|
||||
go func() {
|
||||
t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst)
|
||||
t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger)
|
||||
t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler
|
||||
if err := t.loopy.run(); err != nil {
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: loopyWriter.run returning. Err: %v", err)
|
||||
}
|
||||
}
|
||||
t.conn.Close()
|
||||
t.controlBuf.finish()
|
||||
close(t.writerDone)
|
||||
t.loopy.run()
|
||||
close(t.loopyWriterDone)
|
||||
}()
|
||||
go t.keepalive()
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// operateHeader takes action on the decoded headers.
|
||||
func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) {
|
||||
// operateHeaders takes action on the decoded headers. Returns an error if fatal
|
||||
// error encountered and transport needs to close, otherwise returns nil.
|
||||
func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeadersFrame, handle func(*Stream)) error {
|
||||
// Acquire max stream ID lock for entire duration
|
||||
t.maxStreamMu.Lock()
|
||||
defer t.maxStreamMu.Unlock()
|
||||
@@ -361,33 +347,32 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
rstCode: http2.ErrCodeFrameSize,
|
||||
onWrite: func() {},
|
||||
})
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
if streamID%2 != 1 || streamID <= t.maxStreamID {
|
||||
// illegal gRPC stream id.
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", streamID)
|
||||
}
|
||||
return true
|
||||
return fmt.Errorf("received an illegal stream id: %v. headers frame: %+v", streamID, frame)
|
||||
}
|
||||
t.maxStreamID = streamID
|
||||
|
||||
buf := newRecvBuffer()
|
||||
s := &Stream{
|
||||
id: streamID,
|
||||
st: t,
|
||||
buf: buf,
|
||||
fc: &inFlow{limit: uint32(t.initialWindowSize)},
|
||||
id: streamID,
|
||||
st: t,
|
||||
buf: buf,
|
||||
fc: &inFlow{limit: uint32(t.initialWindowSize)},
|
||||
headerWireLength: int(frame.Header().Length),
|
||||
}
|
||||
var (
|
||||
// If a gRPC Response-Headers has already been received, then it means
|
||||
// that the peer is speaking gRPC and we are in gRPC mode.
|
||||
isGRPC = false
|
||||
mdata = make(map[string][]string)
|
||||
httpMethod string
|
||||
// headerError is set if an error is encountered while parsing the headers
|
||||
headerError bool
|
||||
// if false, content-type was missing or invalid
|
||||
isGRPC = false
|
||||
contentType = ""
|
||||
mdata = make(metadata.MD, len(frame.Fields))
|
||||
httpMethod string
|
||||
// these are set if an error is encountered while parsing the headers
|
||||
protocolError bool
|
||||
headerError *status.Status
|
||||
|
||||
timeoutSet bool
|
||||
timeout time.Duration
|
||||
@@ -398,11 +383,23 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
case "content-type":
|
||||
contentSubtype, validContentType := grpcutil.ContentSubtype(hf.Value)
|
||||
if !validContentType {
|
||||
contentType = hf.Value
|
||||
break
|
||||
}
|
||||
mdata[hf.Name] = append(mdata[hf.Name], hf.Value)
|
||||
s.contentSubtype = contentSubtype
|
||||
isGRPC = true
|
||||
|
||||
case "grpc-accept-encoding":
|
||||
mdata[hf.Name] = append(mdata[hf.Name], hf.Value)
|
||||
if hf.Value == "" {
|
||||
continue
|
||||
}
|
||||
compressors := hf.Value
|
||||
if s.clientAdvertisedCompressors != "" {
|
||||
compressors = s.clientAdvertisedCompressors + "," + compressors
|
||||
}
|
||||
s.clientAdvertisedCompressors = compressors
|
||||
case "grpc-encoding":
|
||||
s.recvCompress = hf.Value
|
||||
case ":method":
|
||||
@@ -413,23 +410,23 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
timeoutSet = true
|
||||
var err error
|
||||
if timeout, err = decodeTimeout(hf.Value); err != nil {
|
||||
headerError = true
|
||||
headerError = status.Newf(codes.Internal, "malformed grpc-timeout: %v", err)
|
||||
}
|
||||
// "Transports must consider requests containing the Connection header
|
||||
// as malformed." - A41
|
||||
case "connection":
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec")
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Received a HEADERS frame with a :connection header which makes the request malformed, as per the HTTP/2 spec")
|
||||
}
|
||||
headerError = true
|
||||
protocolError = true
|
||||
default:
|
||||
if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) {
|
||||
break
|
||||
}
|
||||
v, err := decodeMetadataHeader(hf.Name, hf.Value)
|
||||
if err != nil {
|
||||
headerError = true
|
||||
logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err)
|
||||
headerError = status.Newf(codes.Internal, "malformed binary metadata %q in header %q: %v", hf.Value, hf.Name, err)
|
||||
t.logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err)
|
||||
break
|
||||
}
|
||||
mdata[hf.Name] = append(mdata[hf.Name], v)
|
||||
@@ -443,27 +440,47 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
// error, this takes precedence over a client not speaking gRPC.
|
||||
if len(mdata[":authority"]) > 1 || len(mdata["host"]) > 1 {
|
||||
errMsg := fmt.Sprintf("num values of :authority: %v, num values of host: %v, both must only have 1 value as per HTTP/2 spec", len(mdata[":authority"]), len(mdata["host"]))
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: %v", errMsg)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Aborting the stream early: %v", errMsg)
|
||||
}
|
||||
t.controlBuf.put(&earlyAbortStream{
|
||||
httpStatus: 400,
|
||||
httpStatus: http.StatusBadRequest,
|
||||
streamID: streamID,
|
||||
contentSubtype: s.contentSubtype,
|
||||
status: status.New(codes.Internal, errMsg),
|
||||
rst: !frame.StreamEnded(),
|
||||
})
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
if !isGRPC || headerError {
|
||||
if protocolError {
|
||||
t.controlBuf.put(&cleanupStream{
|
||||
streamID: streamID,
|
||||
rst: true,
|
||||
rstCode: http2.ErrCodeProtocol,
|
||||
onWrite: func() {},
|
||||
})
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
if !isGRPC {
|
||||
t.controlBuf.put(&earlyAbortStream{
|
||||
httpStatus: http.StatusUnsupportedMediaType,
|
||||
streamID: streamID,
|
||||
contentSubtype: s.contentSubtype,
|
||||
status: status.Newf(codes.InvalidArgument, "invalid gRPC request content-type %q", contentType),
|
||||
rst: !frame.StreamEnded(),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
if headerError != nil {
|
||||
t.controlBuf.put(&earlyAbortStream{
|
||||
httpStatus: http.StatusBadRequest,
|
||||
streamID: streamID,
|
||||
contentSubtype: s.contentSubtype,
|
||||
status: headerError,
|
||||
rst: !frame.StreamEnded(),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// "If :authority is missing, Host must be renamed to :authority." - A41
|
||||
@@ -484,9 +501,9 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
s.state = streamReadDone
|
||||
}
|
||||
if timeoutSet {
|
||||
s.ctx, s.cancel = context.WithTimeout(t.ctx, timeout)
|
||||
s.ctx, s.cancel = context.WithTimeout(ctx, timeout)
|
||||
} else {
|
||||
s.ctx, s.cancel = context.WithCancel(t.ctx)
|
||||
s.ctx, s.cancel = context.WithCancel(ctx)
|
||||
}
|
||||
|
||||
// Attach the received metadata to the context.
|
||||
@@ -503,7 +520,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
if t.state != reachable {
|
||||
t.mu.Unlock()
|
||||
s.cancel()
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
if uint32(len(t.activeStreams)) >= t.maxStreams {
|
||||
t.mu.Unlock()
|
||||
@@ -514,13 +531,13 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
onWrite: func() {},
|
||||
})
|
||||
s.cancel()
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
if httpMethod != http.MethodPost {
|
||||
t.mu.Unlock()
|
||||
errMsg := fmt.Sprintf("http2Server.operateHeaders parsed a :method field: %v which should be POST", httpMethod)
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("transport: %v", errMsg)
|
||||
errMsg := fmt.Sprintf("Received a HEADERS frame with :method %q which should be POST", httpMethod)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Aborting the stream early: %v", errMsg)
|
||||
}
|
||||
t.controlBuf.put(&earlyAbortStream{
|
||||
httpStatus: 405,
|
||||
@@ -530,14 +547,14 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
rst: !frame.StreamEnded(),
|
||||
})
|
||||
s.cancel()
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
if t.inTapHandle != nil {
|
||||
var err error
|
||||
if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: s.method}); err != nil {
|
||||
if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: s.method, Header: mdata}); err != nil {
|
||||
t.mu.Unlock()
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Aborting the stream early due to InTapHandle failure: %v", err)
|
||||
}
|
||||
stat, ok := status.FromError(err)
|
||||
if !ok {
|
||||
@@ -550,7 +567,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
status: stat,
|
||||
rst: !frame.StreamEnded(),
|
||||
})
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
}
|
||||
t.activeStreams[streamID] = s
|
||||
@@ -565,19 +582,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
s.requestRead = func(n int) {
|
||||
t.adjustWindow(s, uint32(n))
|
||||
}
|
||||
s.ctx = traceCtx(s.ctx, s.method)
|
||||
for _, sh := range t.stats {
|
||||
s.ctx = sh.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
|
||||
inHeader := &stats.InHeader{
|
||||
FullMethod: s.method,
|
||||
RemoteAddr: t.remoteAddr,
|
||||
LocalAddr: t.localAddr,
|
||||
Compression: s.recvCompress,
|
||||
WireLength: int(frame.Header().Length),
|
||||
Header: metadata.MD(mdata).Copy(),
|
||||
}
|
||||
sh.HandleRPC(s.ctx, inHeader)
|
||||
}
|
||||
s.ctxDone = s.ctx.Done()
|
||||
s.wq = newWriteQuota(defaultWriteQuota, s.ctxDone)
|
||||
s.trReader = &transportReader{
|
||||
@@ -597,22 +601,25 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||
wq: s.wq,
|
||||
})
|
||||
handle(s)
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleStreams receives incoming streams using the given handler. This is
|
||||
// typically run in a separate goroutine.
|
||||
// traceCtx attaches trace to ctx and returns the new context.
|
||||
func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.Context, string) context.Context) {
|
||||
defer close(t.readerDone)
|
||||
func (t *http2Server) HandleStreams(ctx context.Context, handle func(*Stream)) {
|
||||
defer func() {
|
||||
<-t.loopyWriterDone
|
||||
close(t.readerDone)
|
||||
}()
|
||||
for {
|
||||
t.controlBuf.throttle()
|
||||
frame, err := t.framer.fr.ReadFrame()
|
||||
atomic.StoreInt64(&t.lastRead, time.Now().UnixNano())
|
||||
if err != nil {
|
||||
if se, ok := err.(http2.StreamError); ok {
|
||||
if logger.V(logLevel) {
|
||||
logger.Warningf("transport: http2Server.HandleStreams encountered http2.StreamError: %v", se)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Warningf("Encountered http2.StreamError: %v", se)
|
||||
}
|
||||
t.mu.Lock()
|
||||
s := t.activeStreams[se.StreamID]
|
||||
@@ -630,19 +637,16 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.
|
||||
continue
|
||||
}
|
||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||
t.Close()
|
||||
t.Close(err)
|
||||
return
|
||||
}
|
||||
if logger.V(logLevel) {
|
||||
logger.Warningf("transport: http2Server.HandleStreams failed to read frame: %v", err)
|
||||
}
|
||||
t.Close()
|
||||
t.Close(err)
|
||||
return
|
||||
}
|
||||
switch frame := frame.(type) {
|
||||
case *http2.MetaHeadersFrame:
|
||||
if t.operateHeaders(frame, handle, traceCtx) {
|
||||
t.Close()
|
||||
if err := t.operateHeaders(ctx, frame, handle); err != nil {
|
||||
t.Close(err)
|
||||
break
|
||||
}
|
||||
case *http2.DataFrame:
|
||||
@@ -658,8 +662,8 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.
|
||||
case *http2.GoAwayFrame:
|
||||
// TODO: Handle GoAway from the client appropriately.
|
||||
default:
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Received unsupported frame type %T", frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -826,7 +830,7 @@ func (t *http2Server) handleSettings(f *http2.SettingsFrame) {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
t.controlBuf.executeAndPut(func(interface{}) bool {
|
||||
t.controlBuf.executeAndPut(func(any) bool {
|
||||
for _, f := range updateFuncs {
|
||||
f()
|
||||
}
|
||||
@@ -843,8 +847,8 @@ const (
|
||||
|
||||
func (t *http2Server) handlePing(f *http2.PingFrame) {
|
||||
if f.IsAck() {
|
||||
if f.Data == goAwayPing.data && t.drainChan != nil {
|
||||
close(t.drainChan)
|
||||
if f.Data == goAwayPing.data && t.drainEvent != nil {
|
||||
t.drainEvent.Fire()
|
||||
return
|
||||
}
|
||||
// Maybe it's a BDP ping.
|
||||
@@ -886,10 +890,7 @@ func (t *http2Server) handlePing(f *http2.PingFrame) {
|
||||
|
||||
if t.pingStrikes > maxPingStrikes {
|
||||
// Send goaway and close the connection.
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("transport: Got too many pings from the client, closing the connection.")
|
||||
}
|
||||
t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: true})
|
||||
t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: errors.New("got too many pings from the client")})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -913,7 +914,7 @@ func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD)
|
||||
return headerFields
|
||||
}
|
||||
|
||||
func (t *http2Server) checkForHeaderListSize(it interface{}) bool {
|
||||
func (t *http2Server) checkForHeaderListSize(it any) bool {
|
||||
if t.maxSendHeaderListSize == nil {
|
||||
return true
|
||||
}
|
||||
@@ -921,8 +922,8 @@ func (t *http2Server) checkForHeaderListSize(it interface{}) bool {
|
||||
var sz int64
|
||||
for _, f := range hdrFrame.hf {
|
||||
if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
|
||||
if logger.V(logLevel) {
|
||||
logger.Errorf("header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1032,12 +1033,15 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
|
||||
headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(st.Message())})
|
||||
|
||||
if p := st.Proto(); p != nil && len(p.Details) > 0 {
|
||||
// Do not use the user's grpc-status-details-bin (if present) if we are
|
||||
// even attempting to set our own.
|
||||
delete(s.trailer, grpcStatusDetailsBinHeader)
|
||||
stBytes, err := proto.Marshal(p)
|
||||
if err != nil {
|
||||
// TODO: return error instead, when callers are able to handle it.
|
||||
logger.Errorf("transport: failed to marshal rpc status: %v, error: %v", p, err)
|
||||
t.logger.Errorf("Failed to marshal rpc status: %s, error: %v", pretty.ToJSON(p), err)
|
||||
} else {
|
||||
headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status-details-bin", Value: encodeBinHeader(stBytes)})
|
||||
headerFields = append(headerFields, hpack.HeaderField{Name: grpcStatusDetailsBinHeader, Value: encodeBinHeader(stBytes)})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1140,20 +1144,20 @@ func (t *http2Server) keepalive() {
|
||||
if val <= 0 {
|
||||
// The connection has been idle for a duration of keepalive.MaxConnectionIdle or more.
|
||||
// Gracefully close the connection.
|
||||
t.Drain()
|
||||
t.Drain("max_idle")
|
||||
return
|
||||
}
|
||||
idleTimer.Reset(val)
|
||||
case <-ageTimer.C:
|
||||
t.Drain()
|
||||
t.Drain("max_age")
|
||||
ageTimer.Reset(t.kp.MaxConnectionAgeGrace)
|
||||
select {
|
||||
case <-ageTimer.C:
|
||||
// Close the connection after grace period.
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("transport: closing server transport due to maximum connection age.")
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Closing server transport due to maximum connection age")
|
||||
}
|
||||
t.Close()
|
||||
t.controlBuf.put(closeConnection{})
|
||||
case <-t.done:
|
||||
}
|
||||
return
|
||||
@@ -1169,10 +1173,7 @@ func (t *http2Server) keepalive() {
|
||||
continue
|
||||
}
|
||||
if outstandingPing && kpTimeoutLeft <= 0 {
|
||||
if logger.V(logLevel) {
|
||||
logger.Infof("transport: closing server transport due to idleness.")
|
||||
}
|
||||
t.Close()
|
||||
t.Close(fmt.Errorf("keepalive ping not acked within timeout %s", t.kp.Time))
|
||||
return
|
||||
}
|
||||
if !outstandingPing {
|
||||
@@ -1199,30 +1200,29 @@ func (t *http2Server) keepalive() {
|
||||
// Close starts shutting down the http2Server transport.
|
||||
// TODO(zhaoq): Now the destruction is not blocked on any pending streams. This
|
||||
// could cause some resource issue. Revisit this later.
|
||||
func (t *http2Server) Close() {
|
||||
func (t *http2Server) Close(err error) {
|
||||
t.mu.Lock()
|
||||
if t.state == closing {
|
||||
t.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if t.logger.V(logLevel) {
|
||||
t.logger.Infof("Closing: %v", err)
|
||||
}
|
||||
t.state = closing
|
||||
streams := t.activeStreams
|
||||
t.activeStreams = nil
|
||||
t.mu.Unlock()
|
||||
t.controlBuf.finish()
|
||||
close(t.done)
|
||||
if err := t.conn.Close(); err != nil && logger.V(logLevel) {
|
||||
logger.Infof("transport: error closing conn during Close: %v", err)
|
||||
if err := t.conn.Close(); err != nil && t.logger.V(logLevel) {
|
||||
t.logger.Infof("Error closing underlying net.Conn during Close: %v", err)
|
||||
}
|
||||
channelz.RemoveEntry(t.channelzID)
|
||||
// Cancel all active streams.
|
||||
for _, s := range streams {
|
||||
s.cancel()
|
||||
}
|
||||
for _, sh := range t.stats {
|
||||
connEnd := &stats.ConnEnd{}
|
||||
sh.HandleConn(t.ctx, connEnd)
|
||||
}
|
||||
}
|
||||
|
||||
// deleteStream deletes the stream s from transport's active streams.
|
||||
@@ -1288,18 +1288,14 @@ func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, eo
|
||||
})
|
||||
}
|
||||
|
||||
func (t *http2Server) RemoteAddr() net.Addr {
|
||||
return t.remoteAddr
|
||||
}
|
||||
|
||||
func (t *http2Server) Drain() {
|
||||
func (t *http2Server) Drain(debugData string) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.drainChan != nil {
|
||||
if t.drainEvent != nil {
|
||||
return
|
||||
}
|
||||
t.drainChan = make(chan struct{})
|
||||
t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte{}, headsUp: true})
|
||||
t.drainEvent = grpcsync.NewEvent()
|
||||
t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte(debugData), headsUp: true})
|
||||
}
|
||||
|
||||
var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}}
|
||||
@@ -1319,19 +1315,17 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
|
||||
// Stop accepting more streams now.
|
||||
t.state = draining
|
||||
sid := t.maxStreamID
|
||||
retErr := g.closeConn
|
||||
if len(t.activeStreams) == 0 {
|
||||
g.closeConn = true
|
||||
retErr = errors.New("second GOAWAY written and no active streams left to process")
|
||||
}
|
||||
t.mu.Unlock()
|
||||
t.maxStreamMu.Unlock()
|
||||
if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if g.closeConn {
|
||||
// Abruptly close the connection following the GoAway (via
|
||||
// loopywriter). But flush out what's inside the buffer first.
|
||||
t.framer.writer.Flush()
|
||||
return false, fmt.Errorf("transport: Connection closing")
|
||||
if retErr != nil {
|
||||
return false, retErr
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -1343,7 +1337,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
|
||||
// originated before the GoAway reaches the client.
|
||||
// After getting the ack or timer expiration send out another GoAway this
|
||||
// time with an ID of the max stream server intends to process.
|
||||
if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, []byte{}); err != nil {
|
||||
if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, g.debugData); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil {
|
||||
@@ -1353,7 +1347,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
|
||||
timer := time.NewTimer(time.Minute)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-t.drainChan:
|
||||
case <-t.drainEvent.Done():
|
||||
case <-timer.C:
|
||||
case <-t.done:
|
||||
return
|
||||
@@ -1376,11 +1370,11 @@ func (t *http2Server) ChannelzMetric() *channelz.SocketInternalMetric {
|
||||
LastMessageReceivedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgRecvTime)),
|
||||
LocalFlowControlWindow: int64(t.fc.getSize()),
|
||||
SocketOptions: channelz.GetSocketOption(t.conn),
|
||||
LocalAddr: t.localAddr,
|
||||
RemoteAddr: t.remoteAddr,
|
||||
LocalAddr: t.peer.LocalAddr,
|
||||
RemoteAddr: t.peer.Addr,
|
||||
// RemoteName :
|
||||
}
|
||||
if au, ok := t.authInfo.(credentials.ChannelzSecurityInfo); ok {
|
||||
if au, ok := t.peer.AuthInfo.(credentials.ChannelzSecurityInfo); ok {
|
||||
s.Security = au.GetSecurityValue()
|
||||
}
|
||||
s.RemoteFlowControlWindow = t.getOutFlowWindow()
|
||||
@@ -1412,10 +1406,12 @@ func (t *http2Server) getOutFlowWindow() int64 {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *http2Server) getPeer() *peer.Peer {
|
||||
// Peer returns the peer of the transport.
|
||||
func (t *http2Server) Peer() *peer.Peer {
|
||||
return &peer.Peer{
|
||||
Addr: t.remoteAddr,
|
||||
AuthInfo: t.authInfo, // Can be nil
|
||||
Addr: t.peer.Addr,
|
||||
LocalAddr: t.peer.LocalAddr,
|
||||
AuthInfo: t.peer.AuthInfo, // Can be nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1440,6 +1436,6 @@ func GetConnection(ctx context.Context) net.Conn {
|
||||
// SetConnection adds the connection to the context to be able to get
|
||||
// information about the destination ip and port for an incoming RPC. This also
|
||||
// allows any unary or streaming interceptors to see the connection.
|
||||
func setConnection(ctx context.Context, conn net.Conn) context.Context {
|
||||
func SetConnection(ctx context.Context, conn net.Conn) context.Context {
|
||||
return context.WithValue(ctx, connectionKey{}, conn)
|
||||
}
|
||||
|
103
vendor/google.golang.org/grpc/internal/transport/http_util.go
generated
vendored
103
vendor/google.golang.org/grpc/internal/transport/http_util.go
generated
vendored
@@ -21,6 +21,7 @@ package transport
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
@@ -29,16 +30,13 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
spb "google.golang.org/genproto/googleapis/rpc/status"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -85,9 +83,10 @@ var (
|
||||
// 504 Gateway timeout - UNAVAILABLE.
|
||||
http.StatusGatewayTimeout: codes.Unavailable,
|
||||
}
|
||||
logger = grpclog.Component("transport")
|
||||
)
|
||||
|
||||
var grpcStatusDetailsBinHeader = "grpc-status-details-bin"
|
||||
|
||||
// isReservedHeader checks whether hdr belongs to HTTP2 headers
|
||||
// reserved by gRPC protocol. Any other headers are classified as the
|
||||
// user-specified metadata.
|
||||
@@ -103,7 +102,6 @@ func isReservedHeader(hdr string) bool {
|
||||
"grpc-message",
|
||||
"grpc-status",
|
||||
"grpc-timeout",
|
||||
"grpc-status-details-bin",
|
||||
// Intentionally exclude grpc-previous-rpc-attempts and
|
||||
// grpc-retry-pushback-ms, which are "reserved", but their API
|
||||
// intentionally works via metadata.
|
||||
@@ -154,18 +152,6 @@ func decodeMetadataHeader(k, v string) (string, error) {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeGRPCStatusDetails(rawDetails string) (*status.Status, error) {
|
||||
v, err := decodeBinHeader(rawDetails)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st := &spb.Status{}
|
||||
if err = proto.Unmarshal(v, st); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return status.FromProto(st), nil
|
||||
}
|
||||
|
||||
type timeoutUnit uint8
|
||||
|
||||
const (
|
||||
@@ -310,6 +296,7 @@ func decodeGrpcMessageUnchecked(msg string) string {
|
||||
}
|
||||
|
||||
type bufWriter struct {
|
||||
pool *sync.Pool
|
||||
buf []byte
|
||||
offset int
|
||||
batchSize int
|
||||
@@ -317,12 +304,17 @@ type bufWriter struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func newBufWriter(conn net.Conn, batchSize int) *bufWriter {
|
||||
return &bufWriter{
|
||||
buf: make([]byte, batchSize*2),
|
||||
func newBufWriter(conn net.Conn, batchSize int, pool *sync.Pool) *bufWriter {
|
||||
w := &bufWriter{
|
||||
batchSize: batchSize,
|
||||
conn: conn,
|
||||
pool: pool,
|
||||
}
|
||||
// this indicates that we should use non shared buf
|
||||
if pool == nil {
|
||||
w.buf = make([]byte, batchSize)
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *bufWriter) Write(b []byte) (n int, err error) {
|
||||
@@ -330,7 +322,12 @@ func (w *bufWriter) Write(b []byte) (n int, err error) {
|
||||
return 0, w.err
|
||||
}
|
||||
if w.batchSize == 0 { // Buffer has been disabled.
|
||||
return w.conn.Write(b)
|
||||
n, err = w.conn.Write(b)
|
||||
return n, toIOError(err)
|
||||
}
|
||||
if w.buf == nil {
|
||||
b := w.pool.Get().(*[]byte)
|
||||
w.buf = *b
|
||||
}
|
||||
for len(b) > 0 {
|
||||
nn := copy(w.buf[w.offset:], b)
|
||||
@@ -338,13 +335,24 @@ func (w *bufWriter) Write(b []byte) (n int, err error) {
|
||||
w.offset += nn
|
||||
n += nn
|
||||
if w.offset >= w.batchSize {
|
||||
err = w.Flush()
|
||||
err = w.flushKeepBuffer()
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *bufWriter) Flush() error {
|
||||
err := w.flushKeepBuffer()
|
||||
// Only release the buffer if we are in a "shared" mode
|
||||
if w.buf != nil && w.pool != nil {
|
||||
b := w.buf
|
||||
w.pool.Put(&b)
|
||||
w.buf = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *bufWriter) flushKeepBuffer() error {
|
||||
if w.err != nil {
|
||||
return w.err
|
||||
}
|
||||
@@ -352,16 +360,39 @@ func (w *bufWriter) Flush() error {
|
||||
return nil
|
||||
}
|
||||
_, w.err = w.conn.Write(w.buf[:w.offset])
|
||||
w.err = toIOError(w.err)
|
||||
w.offset = 0
|
||||
return w.err
|
||||
}
|
||||
|
||||
type ioError struct {
|
||||
error
|
||||
}
|
||||
|
||||
func (i ioError) Unwrap() error {
|
||||
return i.error
|
||||
}
|
||||
|
||||
func isIOError(err error) bool {
|
||||
return errors.As(err, &ioError{})
|
||||
}
|
||||
|
||||
func toIOError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return ioError{error: err}
|
||||
}
|
||||
|
||||
type framer struct {
|
||||
writer *bufWriter
|
||||
fr *http2.Framer
|
||||
}
|
||||
|
||||
func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderListSize uint32) *framer {
|
||||
var writeBufferPoolMap map[int]*sync.Pool = make(map[int]*sync.Pool)
|
||||
var writeBufferMutex sync.Mutex
|
||||
|
||||
func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, sharedWriteBuffer bool, maxHeaderListSize uint32) *framer {
|
||||
if writeBufferSize < 0 {
|
||||
writeBufferSize = 0
|
||||
}
|
||||
@@ -369,7 +400,11 @@ func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderList
|
||||
if readBufferSize > 0 {
|
||||
r = bufio.NewReaderSize(r, readBufferSize)
|
||||
}
|
||||
w := newBufWriter(conn, writeBufferSize)
|
||||
var pool *sync.Pool
|
||||
if sharedWriteBuffer {
|
||||
pool = getWriteBufferPool(writeBufferSize)
|
||||
}
|
||||
w := newBufWriter(conn, writeBufferSize, pool)
|
||||
f := &framer{
|
||||
writer: w,
|
||||
fr: http2.NewFramer(w, r),
|
||||
@@ -383,6 +418,24 @@ func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderList
|
||||
return f
|
||||
}
|
||||
|
||||
func getWriteBufferPool(writeBufferSize int) *sync.Pool {
|
||||
writeBufferMutex.Lock()
|
||||
defer writeBufferMutex.Unlock()
|
||||
size := writeBufferSize * 2
|
||||
pool, ok := writeBufferPoolMap[size]
|
||||
if ok {
|
||||
return pool
|
||||
}
|
||||
pool = &sync.Pool{
|
||||
New: func() any {
|
||||
b := make([]byte, size)
|
||||
return &b
|
||||
},
|
||||
}
|
||||
writeBufferPoolMap[size] = pool
|
||||
return pool
|
||||
}
|
||||
|
||||
// parseDialTarget returns the network and address to pass to dialer.
|
||||
func parseDialTarget(target string) (string, string) {
|
||||
net := "tcp"
|
||||
|
40
vendor/google.golang.org/grpc/internal/transport/logging.go
generated
vendored
Normal file
40
vendor/google.golang.org/grpc/internal/transport/logging.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
internalgrpclog "google.golang.org/grpc/internal/grpclog"
|
||||
)
|
||||
|
||||
var logger = grpclog.Component("transport")
|
||||
|
||||
func prefixLoggerForServerTransport(p *http2Server) *internalgrpclog.PrefixLogger {
|
||||
return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[server-transport %p] ", p))
|
||||
}
|
||||
|
||||
func prefixLoggerForServerHandlerTransport(p *serverHandlerTransport) *internalgrpclog.PrefixLogger {
|
||||
return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[server-handler-transport %p] ", p))
|
||||
}
|
||||
|
||||
func prefixLoggerForClientTransport(p *http2Client) *internalgrpclog.PrefixLogger {
|
||||
return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[client-transport %p] ", p))
|
||||
}
|
14
vendor/google.golang.org/grpc/internal/transport/proxy.go
generated
vendored
14
vendor/google.golang.org/grpc/internal/transport/proxy.go
generated
vendored
@@ -28,6 +28,8 @@ import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
const proxyAuthHeaderKey = "Proxy-Authorization"
|
||||
@@ -112,7 +114,7 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri
|
||||
// proxyDial dials, connecting to a proxy first if necessary. Checks if a proxy
|
||||
// is necessary, dials, does the HTTP CONNECT handshake, and returns the
|
||||
// connection.
|
||||
func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn, err error) {
|
||||
func proxyDial(ctx context.Context, addr string, grpcUA string) (net.Conn, error) {
|
||||
newAddr := addr
|
||||
proxyURL, err := mapAddress(addr)
|
||||
if err != nil {
|
||||
@@ -122,15 +124,15 @@ func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn,
|
||||
newAddr = proxyURL.Host
|
||||
}
|
||||
|
||||
conn, err = (&net.Dialer{}).DialContext(ctx, "tcp", newAddr)
|
||||
conn, err := internal.NetDialerWithTCPKeepalive().DialContext(ctx, "tcp", newAddr)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
if proxyURL != nil {
|
||||
if proxyURL == nil {
|
||||
// proxy is disabled if proxyURL is nil.
|
||||
conn, err = doHTTPConnectHandshake(ctx, conn, addr, proxyURL, grpcUA)
|
||||
return conn, err
|
||||
}
|
||||
return
|
||||
return doHTTPConnectHandshake(ctx, conn, addr, proxyURL, grpcUA)
|
||||
}
|
||||
|
||||
func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
|
||||
|
70
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
70
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
@@ -37,16 +37,13 @@ import (
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/grpc/tap"
|
||||
)
|
||||
|
||||
// ErrNoHeaders is used as a signal that a trailers only response was received,
|
||||
// and is not a real error.
|
||||
var ErrNoHeaders = errors.New("stream has no headers")
|
||||
|
||||
const logLevel = 2
|
||||
|
||||
type bufferPool struct {
|
||||
@@ -56,7 +53,7 @@ type bufferPool struct {
|
||||
func newBufferPool() *bufferPool {
|
||||
return &bufferPool{
|
||||
pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
@@ -257,6 +254,9 @@ type Stream struct {
|
||||
fc *inFlow
|
||||
wq *writeQuota
|
||||
|
||||
// Holds compressor names passed in grpc-accept-encoding metadata from the
|
||||
// client. This is empty for the client side stream.
|
||||
clientAdvertisedCompressors string
|
||||
// Callback to state application's intentions to read data. This
|
||||
// is used to adjust flow control, if needed.
|
||||
requestRead func(int)
|
||||
@@ -266,7 +266,8 @@ type Stream struct {
|
||||
// headerValid indicates whether a valid header was received. Only
|
||||
// meaningful after headerChan is closed (always call waitOnHeader() before
|
||||
// reading its value). Not valid on server side.
|
||||
headerValid bool
|
||||
headerValid bool
|
||||
headerWireLength int // Only set on server side.
|
||||
|
||||
// hdrMu protects header and trailer metadata on the server-side.
|
||||
hdrMu sync.Mutex
|
||||
@@ -345,8 +346,24 @@ func (s *Stream) RecvCompress() string {
|
||||
}
|
||||
|
||||
// SetSendCompress sets the compression algorithm to the stream.
|
||||
func (s *Stream) SetSendCompress(str string) {
|
||||
s.sendCompress = str
|
||||
func (s *Stream) SetSendCompress(name string) error {
|
||||
if s.isHeaderSent() || s.getState() == streamDone {
|
||||
return errors.New("transport: set send compressor called after headers sent or stream done")
|
||||
}
|
||||
|
||||
s.sendCompress = name
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendCompress returns the send compressor name.
|
||||
func (s *Stream) SendCompress() string {
|
||||
return s.sendCompress
|
||||
}
|
||||
|
||||
// ClientAdvertisedCompressors returns the compressor names advertised by the
|
||||
// client via grpc-accept-encoding header.
|
||||
func (s *Stream) ClientAdvertisedCompressors() string {
|
||||
return s.clientAdvertisedCompressors
|
||||
}
|
||||
|
||||
// Done returns a channel which is closed when it receives the final status
|
||||
@@ -371,14 +388,10 @@ func (s *Stream) Header() (metadata.MD, error) {
|
||||
}
|
||||
s.waitOnHeader()
|
||||
|
||||
if !s.headerValid {
|
||||
if !s.headerValid || s.noHeaders {
|
||||
return nil, s.status.Err()
|
||||
}
|
||||
|
||||
if s.noHeaders {
|
||||
return nil, ErrNoHeaders
|
||||
}
|
||||
|
||||
return s.header.Copy(), nil
|
||||
}
|
||||
|
||||
@@ -414,6 +427,12 @@ func (s *Stream) Context() context.Context {
|
||||
return s.ctx
|
||||
}
|
||||
|
||||
// SetContext sets the context of the stream. This will be deleted once the
|
||||
// stats handler callouts all move to gRPC layer.
|
||||
func (s *Stream) SetContext(ctx context.Context) {
|
||||
s.ctx = ctx
|
||||
}
|
||||
|
||||
// Method returns the method for the stream.
|
||||
func (s *Stream) Method() string {
|
||||
return s.method
|
||||
@@ -426,6 +445,12 @@ func (s *Stream) Status() *status.Status {
|
||||
return s.status
|
||||
}
|
||||
|
||||
// HeaderWireLength returns the size of the headers of the stream as received
|
||||
// from the wire. Valid only on the server.
|
||||
func (s *Stream) HeaderWireLength() int {
|
||||
return s.headerWireLength
|
||||
}
|
||||
|
||||
// SetHeader sets the header metadata. This can be called multiple times.
|
||||
// Server side only.
|
||||
// This should not be called in parallel to other data writes.
|
||||
@@ -540,6 +565,7 @@ type ServerConfig struct {
|
||||
InitialConnWindowSize int32
|
||||
WriteBufferSize int
|
||||
ReadBufferSize int
|
||||
SharedWriteBuffer bool
|
||||
ChannelzParentID *channelz.Identifier
|
||||
MaxHeaderListSize *uint32
|
||||
HeaderTableSize *uint32
|
||||
@@ -573,6 +599,8 @@ type ConnectOptions struct {
|
||||
WriteBufferSize int
|
||||
// ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
|
||||
ReadBufferSize int
|
||||
// SharedWriteBuffer indicates whether connections should reuse write buffer
|
||||
SharedWriteBuffer bool
|
||||
// ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
|
||||
ChannelzParentID *channelz.Identifier
|
||||
// MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
|
||||
@@ -583,8 +611,8 @@ type ConnectOptions struct {
|
||||
|
||||
// NewClientTransport establishes the transport with the required ConnectOptions
|
||||
// and returns it to the caller.
|
||||
func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) {
|
||||
return newHTTP2Client(connectCtx, ctx, addr, opts, onGoAway, onClose)
|
||||
func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onClose func(GoAwayReason)) (ClientTransport, error) {
|
||||
return newHTTP2Client(connectCtx, ctx, addr, opts, onClose)
|
||||
}
|
||||
|
||||
// Options provides additional hints and information for message
|
||||
@@ -684,7 +712,7 @@ type ClientTransport interface {
|
||||
// Write methods for a given Stream will be called serially.
|
||||
type ServerTransport interface {
|
||||
// HandleStreams receives incoming streams using the given handler.
|
||||
HandleStreams(func(*Stream), func(context.Context, string) context.Context)
|
||||
HandleStreams(context.Context, func(*Stream))
|
||||
|
||||
// WriteHeader sends the header metadata for the given stream.
|
||||
// WriteHeader may not be called on all streams.
|
||||
@@ -701,13 +729,13 @@ type ServerTransport interface {
|
||||
// Close tears down the transport. Once it is called, the transport
|
||||
// should not be accessed any more. All the pending streams and their
|
||||
// handlers will be terminated asynchronously.
|
||||
Close()
|
||||
Close(err error)
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
RemoteAddr() net.Addr
|
||||
// Peer returns the peer of the server transport.
|
||||
Peer() *peer.Peer
|
||||
|
||||
// Drain notifies the client this ServerTransport stops accepting new RPCs.
|
||||
Drain()
|
||||
Drain(debugData string)
|
||||
|
||||
// IncrMsgSent increments the number of message sent through this transport.
|
||||
IncrMsgSent()
|
||||
@@ -717,7 +745,7 @@ type ServerTransport interface {
|
||||
}
|
||||
|
||||
// connectionErrorf creates an ConnectionError with the specified error description.
|
||||
func connectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError {
|
||||
func connectionErrorf(temp bool, e error, format string, a ...any) ConnectionError {
|
||||
return ConnectionError{
|
||||
Desc: fmt.Sprintf(format, a...),
|
||||
temp: temp,
|
||||
|
31
vendor/google.golang.org/grpc/metadata/metadata.go
generated
vendored
31
vendor/google.golang.org/grpc/metadata/metadata.go
generated
vendored
@@ -91,7 +91,11 @@ func (md MD) Len() int {
|
||||
|
||||
// Copy returns a copy of md.
|
||||
func (md MD) Copy() MD {
|
||||
return Join(md)
|
||||
out := make(MD, len(md))
|
||||
for k, v := range md {
|
||||
out[k] = copyOf(v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Get obtains the values for a given key.
|
||||
@@ -149,14 +153,16 @@ func Join(mds ...MD) MD {
|
||||
type mdIncomingKey struct{}
|
||||
type mdOutgoingKey struct{}
|
||||
|
||||
// NewIncomingContext creates a new context with incoming md attached.
|
||||
// NewIncomingContext creates a new context with incoming md attached. md must
|
||||
// not be modified after calling this function.
|
||||
func NewIncomingContext(ctx context.Context, md MD) context.Context {
|
||||
return context.WithValue(ctx, mdIncomingKey{}, md)
|
||||
}
|
||||
|
||||
// NewOutgoingContext creates a new context with outgoing md attached. If used
|
||||
// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
|
||||
// overwrite any previously-appended metadata.
|
||||
// overwrite any previously-appended metadata. md must not be modified after
|
||||
// calling this function.
|
||||
func NewOutgoingContext(ctx context.Context, md MD) context.Context {
|
||||
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
|
||||
}
|
||||
@@ -171,8 +177,11 @@ func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context
|
||||
md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
|
||||
added := make([][]string, len(md.added)+1)
|
||||
copy(added, md.added)
|
||||
added[len(added)-1] = make([]string, len(kv))
|
||||
copy(added[len(added)-1], kv)
|
||||
kvCopy := make([]string, 0, len(kv))
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
kvCopy = append(kvCopy, strings.ToLower(kv[i]), kv[i+1])
|
||||
}
|
||||
added[len(added)-1] = kvCopy
|
||||
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added})
|
||||
}
|
||||
|
||||
@@ -196,7 +205,8 @@ func FromIncomingContext(ctx context.Context) (MD, bool) {
|
||||
}
|
||||
|
||||
// ValueFromIncomingContext returns the metadata value corresponding to the metadata
|
||||
// key from the incoming metadata if it exists. Key must be lower-case.
|
||||
// key from the incoming metadata if it exists. Keys are matched in a case insensitive
|
||||
// manner.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
@@ -212,17 +222,16 @@ func ValueFromIncomingContext(ctx context.Context, key string) []string {
|
||||
return copyOf(v)
|
||||
}
|
||||
for k, v := range md {
|
||||
// We need to manually convert all keys to lower case, because MD is a
|
||||
// map, and there's no guarantee that the MD attached to the context is
|
||||
// created using our helper functions.
|
||||
if strings.ToLower(k) == key {
|
||||
// Case insenitive comparison: MD is a map, and there's no guarantee
|
||||
// that the MD attached to the context is created using our helper
|
||||
// functions.
|
||||
if strings.EqualFold(k, key) {
|
||||
return copyOf(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// the returned slice must not be modified in place
|
||||
func copyOf(v []string) []string {
|
||||
vals := make([]string, len(v))
|
||||
copy(vals, v)
|
||||
|
2
vendor/google.golang.org/grpc/peer/peer.go
generated
vendored
2
vendor/google.golang.org/grpc/peer/peer.go
generated
vendored
@@ -32,6 +32,8 @@ import (
|
||||
type Peer struct {
|
||||
// Addr is the peer address.
|
||||
Addr net.Addr
|
||||
// LocalAddr is the local address.
|
||||
LocalAddr net.Addr
|
||||
// AuthInfo is the authentication information of the transport.
|
||||
// It is nil if there is no transport security being used.
|
||||
AuthInfo credentials.AuthInfo
|
||||
|
79
vendor/google.golang.org/grpc/picker_wrapper.go
generated
vendored
79
vendor/google.golang.org/grpc/picker_wrapper.go
generated
vendored
@@ -28,20 +28,25 @@ import (
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
istatus "google.golang.org/grpc/internal/status"
|
||||
"google.golang.org/grpc/internal/transport"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// pickerWrapper is a wrapper of balancer.Picker. It blocks on certain pick
|
||||
// actions and unblock when there's a picker update.
|
||||
type pickerWrapper struct {
|
||||
mu sync.Mutex
|
||||
done bool
|
||||
blockingCh chan struct{}
|
||||
picker balancer.Picker
|
||||
mu sync.Mutex
|
||||
done bool
|
||||
blockingCh chan struct{}
|
||||
picker balancer.Picker
|
||||
statsHandlers []stats.Handler // to record blocking picker calls
|
||||
}
|
||||
|
||||
func newPickerWrapper() *pickerWrapper {
|
||||
return &pickerWrapper{blockingCh: make(chan struct{})}
|
||||
func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper {
|
||||
return &pickerWrapper{
|
||||
blockingCh: make(chan struct{}),
|
||||
statsHandlers: statsHandlers,
|
||||
}
|
||||
}
|
||||
|
||||
// updatePicker is called by UpdateBalancerState. It unblocks all blocked pick.
|
||||
@@ -58,12 +63,16 @@ func (pw *pickerWrapper) updatePicker(p balancer.Picker) {
|
||||
pw.mu.Unlock()
|
||||
}
|
||||
|
||||
func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) func(balancer.DoneInfo) {
|
||||
acw.mu.Lock()
|
||||
ac := acw.ac
|
||||
acw.mu.Unlock()
|
||||
// doneChannelzWrapper performs the following:
|
||||
// - increments the calls started channelz counter
|
||||
// - wraps the done function in the passed in result to increment the calls
|
||||
// failed or calls succeeded channelz counter before invoking the actual
|
||||
// done function.
|
||||
func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
|
||||
ac := acbw.ac
|
||||
ac.incrCallsStarted()
|
||||
return func(b balancer.DoneInfo) {
|
||||
done := result.Done
|
||||
result.Done = func(b balancer.DoneInfo) {
|
||||
if b.Err != nil && b.Err != io.EOF {
|
||||
ac.incrCallsFailed()
|
||||
} else {
|
||||
@@ -82,15 +91,16 @@ func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) f
|
||||
// - the current picker returns other errors and failfast is false.
|
||||
// - the subConn returned by the current picker is not READY
|
||||
// When one of these situations happens, pick blocks until the picker gets updated.
|
||||
func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, func(balancer.DoneInfo), error) {
|
||||
func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) {
|
||||
var ch chan struct{}
|
||||
|
||||
var lastPickErr error
|
||||
|
||||
for {
|
||||
pw.mu.Lock()
|
||||
if pw.done {
|
||||
pw.mu.Unlock()
|
||||
return nil, nil, ErrClientConnClosing
|
||||
return nil, balancer.PickResult{}, ErrClientConnClosing
|
||||
}
|
||||
|
||||
if pw.picker == nil {
|
||||
@@ -111,21 +121,34 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
|
||||
}
|
||||
switch ctx.Err() {
|
||||
case context.DeadlineExceeded:
|
||||
return nil, nil, status.Error(codes.DeadlineExceeded, errStr)
|
||||
return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr)
|
||||
case context.Canceled:
|
||||
return nil, nil, status.Error(codes.Canceled, errStr)
|
||||
return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr)
|
||||
}
|
||||
case <-ch:
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// If the channel is set, it means that the pick call had to wait for a
|
||||
// new picker at some point. Either it's the first iteration and this
|
||||
// function received the first picker, or a picker errored with
|
||||
// ErrNoSubConnAvailable or errored with failfast set to false, which
|
||||
// will trigger a continue to the next iteration. In the first case this
|
||||
// conditional will hit if this call had to block (the channel is set).
|
||||
// In the second case, the only way it will get to this conditional is
|
||||
// if there is a new picker.
|
||||
if ch != nil {
|
||||
for _, sh := range pw.statsHandlers {
|
||||
sh.HandleRPC(ctx, &stats.PickerUpdated{})
|
||||
}
|
||||
}
|
||||
|
||||
ch = pw.blockingCh
|
||||
p := pw.picker
|
||||
pw.mu.Unlock()
|
||||
|
||||
pickResult, err := p.Pick(info)
|
||||
|
||||
if err != nil {
|
||||
if err == balancer.ErrNoSubConnAvailable {
|
||||
continue
|
||||
@@ -136,7 +159,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
|
||||
if istatus.IsRestrictedControlPlaneCode(st) {
|
||||
err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err)
|
||||
}
|
||||
return nil, nil, dropError{error: err}
|
||||
return nil, balancer.PickResult{}, dropError{error: err}
|
||||
}
|
||||
// For all other errors, wait for ready RPCs should block and other
|
||||
// RPCs should fail with unavailable.
|
||||
@@ -144,19 +167,20 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
|
||||
lastPickErr = err
|
||||
continue
|
||||
}
|
||||
return nil, nil, status.Error(codes.Unavailable, err.Error())
|
||||
return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
|
||||
}
|
||||
|
||||
acw, ok := pickResult.SubConn.(*acBalancerWrapper)
|
||||
acbw, ok := pickResult.SubConn.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
logger.Errorf("subconn returned from pick is type %T, not *acBalancerWrapper", pickResult.SubConn)
|
||||
continue
|
||||
}
|
||||
if t := acw.getAddrConn().getReadyTransport(); t != nil {
|
||||
if t := acbw.ac.getReadyTransport(); t != nil {
|
||||
if channelz.IsOn() {
|
||||
return t, doneChannelzWrapper(acw, pickResult.Done), nil
|
||||
doneChannelzWrapper(acbw, &pickResult)
|
||||
return t, pickResult, nil
|
||||
}
|
||||
return t, pickResult.Done, nil
|
||||
return t, pickResult, nil
|
||||
}
|
||||
if pickResult.Done != nil {
|
||||
// Calling done with nil error, no bytes sent and no bytes received.
|
||||
@@ -181,6 +205,17 @@ func (pw *pickerWrapper) close() {
|
||||
close(pw.blockingCh)
|
||||
}
|
||||
|
||||
// reset clears the pickerWrapper and prepares it for being used again when idle
|
||||
// mode is exited.
|
||||
func (pw *pickerWrapper) reset() {
|
||||
pw.mu.Lock()
|
||||
defer pw.mu.Unlock()
|
||||
if pw.done {
|
||||
return
|
||||
}
|
||||
pw.blockingCh = make(chan struct{})
|
||||
}
|
||||
|
||||
// dropError is a wrapper error that indicates the LB policy wishes to drop the
|
||||
// RPC and not retry it.
|
||||
type dropError struct {
|
||||
|
106
vendor/google.golang.org/grpc/pickfirst.go
generated
vendored
106
vendor/google.golang.org/grpc/pickfirst.go
generated
vendored
@@ -19,15 +19,24 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
internalgrpclog "google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
// PickFirstBalancerName is the name of the pick_first balancer.
|
||||
const PickFirstBalancerName = "pick_first"
|
||||
const (
|
||||
// PickFirstBalancerName is the name of the pick_first balancer.
|
||||
PickFirstBalancerName = "pick_first"
|
||||
logPrefix = "[pick-first-lb %p] "
|
||||
)
|
||||
|
||||
func newPickfirstBuilder() balancer.Builder {
|
||||
return &pickfirstBuilder{}
|
||||
@@ -36,22 +45,42 @@ func newPickfirstBuilder() balancer.Builder {
|
||||
type pickfirstBuilder struct{}
|
||||
|
||||
func (*pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
|
||||
return &pickfirstBalancer{cc: cc}
|
||||
b := &pickfirstBalancer{cc: cc}
|
||||
b.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf(logPrefix, b))
|
||||
return b
|
||||
}
|
||||
|
||||
func (*pickfirstBuilder) Name() string {
|
||||
return PickFirstBalancerName
|
||||
}
|
||||
|
||||
type pfConfig struct {
|
||||
serviceconfig.LoadBalancingConfig `json:"-"`
|
||||
|
||||
// If set to true, instructs the LB policy to shuffle the order of the list
|
||||
// of addresses received from the name resolver before attempting to
|
||||
// connect to them.
|
||||
ShuffleAddressList bool `json:"shuffleAddressList"`
|
||||
}
|
||||
|
||||
func (*pickfirstBuilder) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
|
||||
var cfg pfConfig
|
||||
if err := json.Unmarshal(js, &cfg); err != nil {
|
||||
return nil, fmt.Errorf("pickfirst: unable to unmarshal LB policy config: %s, error: %v", string(js), err)
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
type pickfirstBalancer struct {
|
||||
logger *internalgrpclog.PrefixLogger
|
||||
state connectivity.State
|
||||
cc balancer.ClientConn
|
||||
subConn balancer.SubConn
|
||||
}
|
||||
|
||||
func (b *pickfirstBalancer) ResolverError(err error) {
|
||||
if logger.V(2) {
|
||||
logger.Infof("pickfirstBalancer: ResolverError called with error %v", err)
|
||||
if b.logger.V(2) {
|
||||
b.logger.Infof("Received error from the name resolver: %v", err)
|
||||
}
|
||||
if b.subConn == nil {
|
||||
b.state = connectivity.TransientFailure
|
||||
@@ -69,28 +98,49 @@ func (b *pickfirstBalancer) ResolverError(err error) {
|
||||
}
|
||||
|
||||
func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error {
|
||||
if len(state.ResolverState.Addresses) == 0 {
|
||||
addrs := state.ResolverState.Addresses
|
||||
if len(addrs) == 0 {
|
||||
// The resolver reported an empty address list. Treat it like an error by
|
||||
// calling b.ResolverError.
|
||||
if b.subConn != nil {
|
||||
// Remove the old subConn. All addresses were removed, so it is no longer
|
||||
// valid.
|
||||
b.cc.RemoveSubConn(b.subConn)
|
||||
// Shut down the old subConn. All addresses were removed, so it is
|
||||
// no longer valid.
|
||||
b.subConn.Shutdown()
|
||||
b.subConn = nil
|
||||
}
|
||||
b.ResolverError(errors.New("produced zero addresses"))
|
||||
return balancer.ErrBadResolverState
|
||||
}
|
||||
|
||||
// We don't have to guard this block with the env var because ParseConfig
|
||||
// already does so.
|
||||
cfg, ok := state.BalancerConfig.(pfConfig)
|
||||
if state.BalancerConfig != nil && !ok {
|
||||
return fmt.Errorf("pickfirst: received illegal BalancerConfig (type %T): %v", state.BalancerConfig, state.BalancerConfig)
|
||||
}
|
||||
if cfg.ShuffleAddressList {
|
||||
addrs = append([]resolver.Address{}, addrs...)
|
||||
grpcrand.Shuffle(len(addrs), func(i, j int) { addrs[i], addrs[j] = addrs[j], addrs[i] })
|
||||
}
|
||||
|
||||
if b.logger.V(2) {
|
||||
b.logger.Infof("Received new config %s, resolver state %s", pretty.ToJSON(cfg), pretty.ToJSON(state.ResolverState))
|
||||
}
|
||||
|
||||
if b.subConn != nil {
|
||||
b.cc.UpdateAddresses(b.subConn, state.ResolverState.Addresses)
|
||||
b.cc.UpdateAddresses(b.subConn, addrs)
|
||||
return nil
|
||||
}
|
||||
|
||||
subConn, err := b.cc.NewSubConn(state.ResolverState.Addresses, balancer.NewSubConnOptions{})
|
||||
var subConn balancer.SubConn
|
||||
subConn, err := b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{
|
||||
StateListener: func(state balancer.SubConnState) {
|
||||
b.updateSubConnState(subConn, state)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if logger.V(2) {
|
||||
logger.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
|
||||
if b.logger.V(2) {
|
||||
b.logger.Infof("Failed to create new SubConn: %v", err)
|
||||
}
|
||||
b.state = connectivity.TransientFailure
|
||||
b.cc.UpdateState(balancer.State{
|
||||
@@ -102,24 +152,29 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState
|
||||
b.subConn = subConn
|
||||
b.state = connectivity.Idle
|
||||
b.cc.UpdateState(balancer.State{
|
||||
ConnectivityState: connectivity.Idle,
|
||||
Picker: &picker{result: balancer.PickResult{SubConn: b.subConn}},
|
||||
ConnectivityState: connectivity.Connecting,
|
||||
Picker: &picker{err: balancer.ErrNoSubConnAvailable},
|
||||
})
|
||||
b.subConn.Connect()
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSubConnState is unused as a StateListener is always registered when
|
||||
// creating SubConns.
|
||||
func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state balancer.SubConnState) {
|
||||
if logger.V(2) {
|
||||
logger.Infof("pickfirstBalancer: UpdateSubConnState: %p, %v", subConn, state)
|
||||
b.logger.Errorf("UpdateSubConnState(%v, %+v) called unexpectedly", subConn, state)
|
||||
}
|
||||
|
||||
func (b *pickfirstBalancer) updateSubConnState(subConn balancer.SubConn, state balancer.SubConnState) {
|
||||
if b.logger.V(2) {
|
||||
b.logger.Infof("Received SubConn state update: %p, %+v", subConn, state)
|
||||
}
|
||||
if b.subConn != subConn {
|
||||
if logger.V(2) {
|
||||
logger.Infof("pickfirstBalancer: ignored state change because subConn is not recognized")
|
||||
if b.logger.V(2) {
|
||||
b.logger.Infof("Ignored state change because subConn is not recognized")
|
||||
}
|
||||
return
|
||||
}
|
||||
b.state = state.ConnectivityState
|
||||
if state.ConnectivityState == connectivity.Shutdown {
|
||||
b.subConn = nil
|
||||
return
|
||||
@@ -132,11 +187,21 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b
|
||||
Picker: &picker{result: balancer.PickResult{SubConn: subConn}},
|
||||
})
|
||||
case connectivity.Connecting:
|
||||
if b.state == connectivity.TransientFailure {
|
||||
// We stay in TransientFailure until we are Ready. See A62.
|
||||
return
|
||||
}
|
||||
b.cc.UpdateState(balancer.State{
|
||||
ConnectivityState: state.ConnectivityState,
|
||||
Picker: &picker{err: balancer.ErrNoSubConnAvailable},
|
||||
})
|
||||
case connectivity.Idle:
|
||||
if b.state == connectivity.TransientFailure {
|
||||
// We stay in TransientFailure until we are Ready. Also kick the
|
||||
// subConn out of Idle into Connecting. See A62.
|
||||
b.subConn.Connect()
|
||||
return
|
||||
}
|
||||
b.cc.UpdateState(balancer.State{
|
||||
ConnectivityState: state.ConnectivityState,
|
||||
Picker: &idlePicker{subConn: subConn},
|
||||
@@ -147,6 +212,7 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b
|
||||
Picker: &picker{err: state.ConnectionError},
|
||||
})
|
||||
}
|
||||
b.state = state.ConnectivityState
|
||||
}
|
||||
|
||||
func (b *pickfirstBalancer) Close() {
|
||||
|
2
vendor/google.golang.org/grpc/preloader.go
generated
vendored
2
vendor/google.golang.org/grpc/preloader.go
generated
vendored
@@ -37,7 +37,7 @@ type PreparedMsg struct {
|
||||
}
|
||||
|
||||
// Encode marshalls and compresses the message using the codec and compressor for the stream.
|
||||
func (p *PreparedMsg) Encode(s Stream, msg interface{}) error {
|
||||
func (p *PreparedMsg) Encode(s Stream, msg any) error {
|
||||
ctx := s.Context()
|
||||
rpcInfo, ok := rpcInfoFromContext(ctx)
|
||||
if !ok {
|
||||
|
7
vendor/google.golang.org/grpc/regenerate.sh
generated
vendored
7
vendor/google.golang.org/grpc/regenerate.sh
generated
vendored
@@ -57,7 +57,8 @@ LEGACY_SOURCES=(
|
||||
${WORKDIR}/grpc-proto/grpc/health/v1/health.proto
|
||||
${WORKDIR}/grpc-proto/grpc/lb/v1/load_balancer.proto
|
||||
profiling/proto/service.proto
|
||||
reflection/grpc_reflection_v1alpha/reflection.proto
|
||||
${WORKDIR}/grpc-proto/grpc/reflection/v1alpha/reflection.proto
|
||||
${WORKDIR}/grpc-proto/grpc/reflection/v1/reflection.proto
|
||||
)
|
||||
|
||||
# Generates only the new gRPC Service symbols
|
||||
@@ -119,8 +120,4 @@ mv ${WORKDIR}/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* ${WORKDIR}/out/
|
||||
# see grpc_testing_not_regenerate/README.md for details.
|
||||
rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testing_not_regenerate/*.pb.go
|
||||
|
||||
# grpc/testing does not have a go_package option.
|
||||
mv ${WORKDIR}/out/grpc/testing/*.pb.go interop/grpc_testing/
|
||||
mv ${WORKDIR}/out/grpc/core/*.pb.go interop/grpc_testing/core/
|
||||
|
||||
cp -R ${WORKDIR}/out/google.golang.org/grpc/* .
|
||||
|
36
vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
generated
vendored
Normal file
36
vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package dns implements a dns resolver to be installed as the default resolver
|
||||
// in grpc.
|
||||
//
|
||||
// Deprecated: this package is imported by grpc and should not need to be
|
||||
// imported directly by users.
|
||||
package dns
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/internal/resolver/dns"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
|
||||
//
|
||||
// Deprecated: import grpc and use resolver.Get("dns") instead.
|
||||
func NewBuilder() resolver.Builder {
|
||||
return dns.NewBuilder()
|
||||
}
|
123
vendor/google.golang.org/grpc/resolver/map.go
generated
vendored
123
vendor/google.golang.org/grpc/resolver/map.go
generated
vendored
@@ -20,7 +20,7 @@ package resolver
|
||||
|
||||
type addressMapEntry struct {
|
||||
addr Address
|
||||
value interface{}
|
||||
value any
|
||||
}
|
||||
|
||||
// AddressMap is a map of addresses to arbitrary values taking into account
|
||||
@@ -69,7 +69,7 @@ func (l addressMapEntryList) find(addr Address) int {
|
||||
}
|
||||
|
||||
// Get returns the value for the address in the map, if present.
|
||||
func (a *AddressMap) Get(addr Address) (value interface{}, ok bool) {
|
||||
func (a *AddressMap) Get(addr Address) (value any, ok bool) {
|
||||
addrKey := toMapKey(&addr)
|
||||
entryList := a.m[addrKey]
|
||||
if entry := entryList.find(addr); entry != -1 {
|
||||
@@ -79,7 +79,7 @@ func (a *AddressMap) Get(addr Address) (value interface{}, ok bool) {
|
||||
}
|
||||
|
||||
// Set updates or adds the value to the address in the map.
|
||||
func (a *AddressMap) Set(addr Address, value interface{}) {
|
||||
func (a *AddressMap) Set(addr Address, value any) {
|
||||
addrKey := toMapKey(&addr)
|
||||
entryList := a.m[addrKey]
|
||||
if entry := entryList.find(addr); entry != -1 {
|
||||
@@ -127,8 +127,8 @@ func (a *AddressMap) Keys() []Address {
|
||||
}
|
||||
|
||||
// Values returns a slice of all current map values.
|
||||
func (a *AddressMap) Values() []interface{} {
|
||||
ret := make([]interface{}, 0, a.Len())
|
||||
func (a *AddressMap) Values() []any {
|
||||
ret := make([]any, 0, a.Len())
|
||||
for _, entryList := range a.m {
|
||||
for _, entry := range entryList {
|
||||
ret = append(ret, entry.value)
|
||||
@@ -136,3 +136,116 @@ func (a *AddressMap) Values() []interface{} {
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type endpointNode struct {
|
||||
addrs map[string]struct{}
|
||||
}
|
||||
|
||||
// Equal returns whether the unordered set of addrs are the same between the
|
||||
// endpoint nodes.
|
||||
func (en *endpointNode) Equal(en2 *endpointNode) bool {
|
||||
if len(en.addrs) != len(en2.addrs) {
|
||||
return false
|
||||
}
|
||||
for addr := range en.addrs {
|
||||
if _, ok := en2.addrs[addr]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func toEndpointNode(endpoint Endpoint) endpointNode {
|
||||
en := make(map[string]struct{})
|
||||
for _, addr := range endpoint.Addresses {
|
||||
en[addr.Addr] = struct{}{}
|
||||
}
|
||||
return endpointNode{
|
||||
addrs: en,
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointMap is a map of endpoints to arbitrary values keyed on only the
|
||||
// unordered set of address strings within an endpoint. This map is not thread
|
||||
// safe, thus it is unsafe to access concurrently. Must be created via
|
||||
// NewEndpointMap; do not construct directly.
|
||||
type EndpointMap struct {
|
||||
endpoints map[*endpointNode]any
|
||||
}
|
||||
|
||||
// NewEndpointMap creates a new EndpointMap.
|
||||
func NewEndpointMap() *EndpointMap {
|
||||
return &EndpointMap{
|
||||
endpoints: make(map[*endpointNode]any),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the value for the address in the map, if present.
|
||||
func (em *EndpointMap) Get(e Endpoint) (value any, ok bool) {
|
||||
en := toEndpointNode(e)
|
||||
if endpoint := em.find(en); endpoint != nil {
|
||||
return em.endpoints[endpoint], true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Set updates or adds the value to the address in the map.
|
||||
func (em *EndpointMap) Set(e Endpoint, value any) {
|
||||
en := toEndpointNode(e)
|
||||
if endpoint := em.find(en); endpoint != nil {
|
||||
em.endpoints[endpoint] = value
|
||||
return
|
||||
}
|
||||
em.endpoints[&en] = value
|
||||
}
|
||||
|
||||
// Len returns the number of entries in the map.
|
||||
func (em *EndpointMap) Len() int {
|
||||
return len(em.endpoints)
|
||||
}
|
||||
|
||||
// Keys returns a slice of all current map keys, as endpoints specifying the
|
||||
// addresses present in the endpoint keys, in which uniqueness is determined by
|
||||
// the unordered set of addresses. Thus, endpoint information returned is not
|
||||
// the full endpoint data (drops duplicated addresses and attributes) but can be
|
||||
// used for EndpointMap accesses.
|
||||
func (em *EndpointMap) Keys() []Endpoint {
|
||||
ret := make([]Endpoint, 0, len(em.endpoints))
|
||||
for en := range em.endpoints {
|
||||
var endpoint Endpoint
|
||||
for addr := range en.addrs {
|
||||
endpoint.Addresses = append(endpoint.Addresses, Address{Addr: addr})
|
||||
}
|
||||
ret = append(ret, endpoint)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Values returns a slice of all current map values.
|
||||
func (em *EndpointMap) Values() []any {
|
||||
ret := make([]any, 0, len(em.endpoints))
|
||||
for _, val := range em.endpoints {
|
||||
ret = append(ret, val)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// find returns a pointer to the endpoint node in em if the endpoint node is
|
||||
// already present. If not found, nil is returned. The comparisons are done on
|
||||
// the unordered set of addresses within an endpoint.
|
||||
func (em EndpointMap) find(e endpointNode) *endpointNode {
|
||||
for endpoint := range em.endpoints {
|
||||
if e.Equal(endpoint) {
|
||||
return endpoint
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes the specified endpoint from the map.
|
||||
func (em *EndpointMap) Delete(e Endpoint) {
|
||||
en := toEndpointNode(e)
|
||||
if entry := em.find(en); entry != nil {
|
||||
delete(em.endpoints, entry)
|
||||
}
|
||||
}
|
||||
|
152
vendor/google.golang.org/grpc/resolver/resolver.go
generated
vendored
152
vendor/google.golang.org/grpc/resolver/resolver.go
generated
vendored
@@ -22,12 +22,13 @@ package resolver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/attributes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
@@ -40,8 +41,9 @@ var (
|
||||
|
||||
// TODO(bar) install dns resolver in init(){}.
|
||||
|
||||
// Register registers the resolver builder to the resolver map. b.Scheme will be
|
||||
// used as the scheme registered with this builder.
|
||||
// Register registers the resolver builder to the resolver map. b.Scheme will
|
||||
// be used as the scheme registered with this builder. The registry is case
|
||||
// sensitive, and schemes should not contain any uppercase characters.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Resolvers are
|
||||
@@ -75,25 +77,6 @@ func GetDefaultScheme() string {
|
||||
return defaultScheme
|
||||
}
|
||||
|
||||
// AddressType indicates the address type returned by name resolution.
|
||||
//
|
||||
// Deprecated: use Attributes in Address instead.
|
||||
type AddressType uint8
|
||||
|
||||
const (
|
||||
// Backend indicates the address is for a backend server.
|
||||
//
|
||||
// Deprecated: use Attributes in Address instead.
|
||||
Backend AddressType = iota
|
||||
// GRPCLB indicates the address is for a grpclb load balancer.
|
||||
//
|
||||
// Deprecated: to select the GRPCLB load balancing policy, use a service
|
||||
// config with a corresponding loadBalancingConfig. To supply balancer
|
||||
// addresses to the GRPCLB load balancing policy, set State.Attributes
|
||||
// using balancer/grpclb/state.Set.
|
||||
GRPCLB
|
||||
)
|
||||
|
||||
// Address represents a server the client connects to.
|
||||
//
|
||||
// # Experimental
|
||||
@@ -109,9 +92,6 @@ type Address struct {
|
||||
// the address, instead of the hostname from the Dial target string. In most cases,
|
||||
// this should not be set.
|
||||
//
|
||||
// If Type is GRPCLB, ServerName should be the name of the remote load
|
||||
// balancer, not the name of the backend.
|
||||
//
|
||||
// WARNING: ServerName must only be populated with trusted values. It
|
||||
// is insecure to populate it with data from untrusted inputs since untrusted
|
||||
// values could be used to bypass the authority checks performed by TLS.
|
||||
@@ -122,34 +102,46 @@ type Address struct {
|
||||
Attributes *attributes.Attributes
|
||||
|
||||
// BalancerAttributes contains arbitrary data about this address intended
|
||||
// for consumption by the LB policy. These attribes do not affect SubConn
|
||||
// for consumption by the LB policy. These attributes do not affect SubConn
|
||||
// creation, connection establishment, handshaking, etc.
|
||||
BalancerAttributes *attributes.Attributes
|
||||
|
||||
// Type is the type of this address.
|
||||
//
|
||||
// Deprecated: use Attributes instead.
|
||||
Type AddressType
|
||||
// Deprecated: when an Address is inside an Endpoint, this field should not
|
||||
// be used, and it will eventually be removed entirely.
|
||||
BalancerAttributes *attributes.Attributes
|
||||
|
||||
// Metadata is the information associated with Addr, which may be used
|
||||
// to make load balancing decision.
|
||||
//
|
||||
// Deprecated: use Attributes instead.
|
||||
Metadata interface{}
|
||||
Metadata any
|
||||
}
|
||||
|
||||
// Equal returns whether a and o are identical. Metadata is compared directly,
|
||||
// not with any recursive introspection.
|
||||
//
|
||||
// This method compares all fields of the address. When used to tell apart
|
||||
// addresses during subchannel creation or connection establishment, it might be
|
||||
// more appropriate for the caller to implement custom equality logic.
|
||||
func (a Address) Equal(o Address) bool {
|
||||
return a.Addr == o.Addr && a.ServerName == o.ServerName &&
|
||||
a.Attributes.Equal(o.Attributes) &&
|
||||
a.BalancerAttributes.Equal(o.BalancerAttributes) &&
|
||||
a.Type == o.Type && a.Metadata == o.Metadata
|
||||
a.Metadata == o.Metadata
|
||||
}
|
||||
|
||||
// String returns JSON formatted string representation of the address.
|
||||
func (a Address) String() string {
|
||||
return pretty.ToJSON(a)
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("{Addr: %q, ", a.Addr))
|
||||
sb.WriteString(fmt.Sprintf("ServerName: %q, ", a.ServerName))
|
||||
if a.Attributes != nil {
|
||||
sb.WriteString(fmt.Sprintf("Attributes: %v, ", a.Attributes.String()))
|
||||
}
|
||||
if a.BalancerAttributes != nil {
|
||||
sb.WriteString(fmt.Sprintf("BalancerAttributes: %v", a.BalancerAttributes.String()))
|
||||
}
|
||||
sb.WriteString("}")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// BuildOptions includes additional information for the builder to create
|
||||
@@ -178,11 +170,37 @@ type BuildOptions struct {
|
||||
Dialer func(context.Context, string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// An Endpoint is one network endpoint, or server, which may have multiple
|
||||
// addresses with which it can be accessed.
|
||||
type Endpoint struct {
|
||||
// Addresses contains a list of addresses used to access this endpoint.
|
||||
Addresses []Address
|
||||
|
||||
// Attributes contains arbitrary data about this endpoint intended for
|
||||
// consumption by the LB policy.
|
||||
Attributes *attributes.Attributes
|
||||
}
|
||||
|
||||
// State contains the current Resolver state relevant to the ClientConn.
|
||||
type State struct {
|
||||
// Addresses is the latest set of resolved addresses for the target.
|
||||
//
|
||||
// If a resolver sets Addresses but does not set Endpoints, one Endpoint
|
||||
// will be created for each Address before the State is passed to the LB
|
||||
// policy. The BalancerAttributes of each entry in Addresses will be set
|
||||
// in Endpoints.Attributes, and be cleared in the Endpoint's Address's
|
||||
// BalancerAttributes.
|
||||
//
|
||||
// Soon, Addresses will be deprecated and replaced fully by Endpoints.
|
||||
Addresses []Address
|
||||
|
||||
// Endpoints is the latest set of resolved endpoints for the target.
|
||||
//
|
||||
// If a resolver produces a State containing Endpoints but not Addresses,
|
||||
// it must take care to ensure the LB policies it selects will support
|
||||
// Endpoints.
|
||||
Endpoints []Endpoint
|
||||
|
||||
// ServiceConfig contains the result from parsing the latest service
|
||||
// config. If it is nil, it indicates no service config is present or the
|
||||
// resolver does not provide service configs.
|
||||
@@ -202,6 +220,15 @@ type State struct {
|
||||
// gRPC to add new methods to this interface.
|
||||
type ClientConn interface {
|
||||
// UpdateState updates the state of the ClientConn appropriately.
|
||||
//
|
||||
// If an error is returned, the resolver should try to resolve the
|
||||
// target again. The resolver should use a backoff timer to prevent
|
||||
// overloading the server with requests. If a resolver is certain that
|
||||
// reresolving will not change the result, e.g. because it is
|
||||
// a watch-based resolver, returned errors can be ignored.
|
||||
//
|
||||
// If the resolved State is the same as the last reported one, calling
|
||||
// UpdateState can be omitted.
|
||||
UpdateState(State) error
|
||||
// ReportError notifies the ClientConn that the Resolver encountered an
|
||||
// error. The ClientConn will notify the load balancer and begin calling
|
||||
@@ -213,11 +240,6 @@ type ClientConn interface {
|
||||
//
|
||||
// Deprecated: Use UpdateState instead.
|
||||
NewAddress(addresses []Address)
|
||||
// NewServiceConfig is called by resolver to notify ClientConn a new
|
||||
// service config. The service config should be provided as a json string.
|
||||
//
|
||||
// Deprecated: Use UpdateState instead.
|
||||
NewServiceConfig(serviceConfig string)
|
||||
// ParseServiceConfig parses the provided service config and returns an
|
||||
// object that provides the parsed config.
|
||||
ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult
|
||||
@@ -233,23 +255,7 @@ type ClientConn interface {
|
||||
// target does not contain a scheme or if the parsed scheme is not registered
|
||||
// (i.e. no corresponding resolver available to resolve the endpoint), we will
|
||||
// apply the default scheme, and will attempt to reparse it.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "dns://some_authority/foo.bar"
|
||||
// Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"}
|
||||
// - "foo.bar"
|
||||
// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"}
|
||||
// - "unknown_scheme://authority/endpoint"
|
||||
// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"}
|
||||
type Target struct {
|
||||
// Deprecated: use URL.Scheme instead.
|
||||
Scheme string
|
||||
// Deprecated: use URL.Host instead.
|
||||
Authority string
|
||||
// Deprecated: use URL.Path or URL.Opaque instead. The latter is set when
|
||||
// the former is empty.
|
||||
Endpoint string
|
||||
// URL contains the parsed dial target with an optional default scheme added
|
||||
// to it if the original dial target contained no scheme or contained an
|
||||
// unregistered scheme. Any query params specified in the original dial
|
||||
@@ -257,6 +263,29 @@ type Target struct {
|
||||
URL url.URL
|
||||
}
|
||||
|
||||
// Endpoint retrieves endpoint without leading "/" from either `URL.Path`
|
||||
// or `URL.Opaque`. The latter is used when the former is empty.
|
||||
func (t Target) Endpoint() string {
|
||||
endpoint := t.URL.Path
|
||||
if endpoint == "" {
|
||||
endpoint = t.URL.Opaque
|
||||
}
|
||||
// For targets of the form "[scheme]://[authority]/endpoint, the endpoint
|
||||
// value returned from url.Parse() contains a leading "/". Although this is
|
||||
// in accordance with RFC 3986, we do not want to break existing resolver
|
||||
// implementations which expect the endpoint without the leading "/". So, we
|
||||
// end up stripping the leading "/" here. But this will result in an
|
||||
// incorrect parsing for something like "unix:///path/to/socket". Since we
|
||||
// own the "unix" resolver, we can workaround in the unix resolver by using
|
||||
// the `URL` field.
|
||||
return strings.TrimPrefix(endpoint, "/")
|
||||
}
|
||||
|
||||
// String returns a string representation of Target.
|
||||
func (t Target) String() string {
|
||||
return t.URL.String()
|
||||
}
|
||||
|
||||
// Builder creates a resolver that will be used to watch name resolution updates.
|
||||
type Builder interface {
|
||||
// Build creates a new resolver for the given target.
|
||||
@@ -264,8 +293,10 @@ type Builder interface {
|
||||
// gRPC dial calls Build synchronously, and fails if the returned error is
|
||||
// not nil.
|
||||
Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error)
|
||||
// Scheme returns the scheme supported by this resolver.
|
||||
// Scheme is defined at https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
||||
// Scheme returns the scheme supported by this resolver. Scheme is defined
|
||||
// at https://github.com/grpc/grpc/blob/master/doc/naming.md. The returned
|
||||
// string should not contain uppercase characters, as they will not match
|
||||
// the parsed target's scheme as defined in RFC 3986.
|
||||
Scheme() string
|
||||
}
|
||||
|
||||
@@ -283,10 +314,3 @@ type Resolver interface {
|
||||
// Close closes the resolver.
|
||||
Close()
|
||||
}
|
||||
|
||||
// UnregisterForTesting removes the resolver builder with the given scheme from the
|
||||
// resolver map.
|
||||
// This function is for testing only.
|
||||
func UnregisterForTesting(scheme string) {
|
||||
delete(m, scheme)
|
||||
}
|
||||
|
176
vendor/google.golang.org/grpc/resolver_conn_wrapper.go
generated
vendored
176
vendor/google.golang.org/grpc/resolver_conn_wrapper.go
generated
vendored
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
// ccResolverWrapper is a wrapper on top of cc for resolvers.
|
||||
// It implements resolver.ClientConn interface.
|
||||
type ccResolverWrapper struct {
|
||||
cc *ClientConn
|
||||
resolverMu sync.Mutex
|
||||
resolver resolver.Resolver
|
||||
done *grpcsync.Event
|
||||
curState resolver.State
|
||||
|
||||
incomingMu sync.Mutex // Synchronizes all the incoming calls.
|
||||
}
|
||||
|
||||
// newCCResolverWrapper uses the resolver.Builder to build a Resolver and
|
||||
// returns a ccResolverWrapper object which wraps the newly built resolver.
|
||||
func newCCResolverWrapper(cc *ClientConn, rb resolver.Builder) (*ccResolverWrapper, error) {
|
||||
ccr := &ccResolverWrapper{
|
||||
cc: cc,
|
||||
done: grpcsync.NewEvent(),
|
||||
}
|
||||
|
||||
var credsClone credentials.TransportCredentials
|
||||
if creds := cc.dopts.copts.TransportCredentials; creds != nil {
|
||||
credsClone = creds.Clone()
|
||||
}
|
||||
rbo := resolver.BuildOptions{
|
||||
DisableServiceConfig: cc.dopts.disableServiceConfig,
|
||||
DialCreds: credsClone,
|
||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||
Dialer: cc.dopts.copts.Dialer,
|
||||
}
|
||||
|
||||
var err error
|
||||
// We need to hold the lock here while we assign to the ccr.resolver field
|
||||
// to guard against a data race caused by the following code path,
|
||||
// rb.Build-->ccr.ReportError-->ccr.poll-->ccr.resolveNow, would end up
|
||||
// accessing ccr.resolver which is being assigned here.
|
||||
ccr.resolverMu.Lock()
|
||||
defer ccr.resolverMu.Unlock()
|
||||
ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, rbo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ccr, nil
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) {
|
||||
ccr.resolverMu.Lock()
|
||||
if !ccr.done.HasFired() {
|
||||
ccr.resolver.ResolveNow(o)
|
||||
}
|
||||
ccr.resolverMu.Unlock()
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) close() {
|
||||
ccr.resolverMu.Lock()
|
||||
ccr.resolver.Close()
|
||||
ccr.done.Fire()
|
||||
ccr.resolverMu.Unlock()
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
|
||||
ccr.incomingMu.Lock()
|
||||
defer ccr.incomingMu.Unlock()
|
||||
if ccr.done.HasFired() {
|
||||
return nil
|
||||
}
|
||||
ccr.addChannelzTraceEvent(s)
|
||||
ccr.curState = s
|
||||
if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState {
|
||||
return balancer.ErrBadResolverState
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) ReportError(err error) {
|
||||
ccr.incomingMu.Lock()
|
||||
defer ccr.incomingMu.Unlock()
|
||||
if ccr.done.HasFired() {
|
||||
return
|
||||
}
|
||||
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
|
||||
ccr.cc.updateResolverState(resolver.State{}, err)
|
||||
}
|
||||
|
||||
// NewAddress is called by the resolver implementation to send addresses to gRPC.
|
||||
func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
|
||||
ccr.incomingMu.Lock()
|
||||
defer ccr.incomingMu.Unlock()
|
||||
if ccr.done.HasFired() {
|
||||
return
|
||||
}
|
||||
ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
|
||||
ccr.curState.Addresses = addrs
|
||||
ccr.cc.updateResolverState(ccr.curState, nil)
|
||||
}
|
||||
|
||||
// NewServiceConfig is called by the resolver implementation to send service
|
||||
// configs to gRPC.
|
||||
func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
|
||||
ccr.incomingMu.Lock()
|
||||
defer ccr.incomingMu.Unlock()
|
||||
if ccr.done.HasFired() {
|
||||
return
|
||||
}
|
||||
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: got new service config: %s", sc)
|
||||
if ccr.cc.dopts.disableServiceConfig {
|
||||
channelz.Info(logger, ccr.cc.channelzID, "Service config lookups disabled; ignoring config")
|
||||
return
|
||||
}
|
||||
scpr := parseServiceConfig(sc)
|
||||
if scpr.Err != nil {
|
||||
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err)
|
||||
return
|
||||
}
|
||||
ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
|
||||
ccr.curState.ServiceConfig = scpr
|
||||
ccr.cc.updateResolverState(ccr.curState, nil)
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
|
||||
return parseServiceConfig(scJSON)
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
|
||||
var updates []string
|
||||
var oldSC, newSC *ServiceConfig
|
||||
var oldOK, newOK bool
|
||||
if ccr.curState.ServiceConfig != nil {
|
||||
oldSC, oldOK = ccr.curState.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if s.ServiceConfig != nil {
|
||||
newSC, newOK = s.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if oldOK != newOK || (oldOK && newOK && oldSC.rawJSONString != newSC.rawJSONString) {
|
||||
updates = append(updates, "service config updated")
|
||||
}
|
||||
if len(ccr.curState.Addresses) > 0 && len(s.Addresses) == 0 {
|
||||
updates = append(updates, "resolver returned an empty address list")
|
||||
} else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 {
|
||||
updates = append(updates, "resolver returned new addresses")
|
||||
}
|
||||
channelz.Infof(logger, ccr.cc.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
|
||||
}
|
197
vendor/google.golang.org/grpc/resolver_wrapper.go
generated
vendored
Normal file
197
vendor/google.golang.org/grpc/resolver_wrapper.go
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
// ccResolverWrapper is a wrapper on top of cc for resolvers.
|
||||
// It implements resolver.ClientConn interface.
|
||||
type ccResolverWrapper struct {
|
||||
// The following fields are initialized when the wrapper is created and are
|
||||
// read-only afterwards, and therefore can be accessed without a mutex.
|
||||
cc *ClientConn
|
||||
ignoreServiceConfig bool
|
||||
serializer *grpcsync.CallbackSerializer
|
||||
serializerCancel context.CancelFunc
|
||||
|
||||
resolver resolver.Resolver // only accessed within the serializer
|
||||
|
||||
// The following fields are protected by mu. Caller must take cc.mu before
|
||||
// taking mu.
|
||||
mu sync.Mutex
|
||||
curState resolver.State
|
||||
closed bool
|
||||
}
|
||||
|
||||
// newCCResolverWrapper initializes the ccResolverWrapper. It can only be used
|
||||
// after calling start, which builds the resolver.
|
||||
func newCCResolverWrapper(cc *ClientConn) *ccResolverWrapper {
|
||||
ctx, cancel := context.WithCancel(cc.ctx)
|
||||
return &ccResolverWrapper{
|
||||
cc: cc,
|
||||
ignoreServiceConfig: cc.dopts.disableServiceConfig,
|
||||
serializer: grpcsync.NewCallbackSerializer(ctx),
|
||||
serializerCancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// start builds the name resolver using the resolver.Builder in cc and returns
|
||||
// any error encountered. It must always be the first operation performed on
|
||||
// any newly created ccResolverWrapper, except that close may be called instead.
|
||||
func (ccr *ccResolverWrapper) start() error {
|
||||
errCh := make(chan error)
|
||||
ccr.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
opts := resolver.BuildOptions{
|
||||
DisableServiceConfig: ccr.cc.dopts.disableServiceConfig,
|
||||
DialCreds: ccr.cc.dopts.copts.TransportCredentials,
|
||||
CredsBundle: ccr.cc.dopts.copts.CredsBundle,
|
||||
Dialer: ccr.cc.dopts.copts.Dialer,
|
||||
}
|
||||
var err error
|
||||
ccr.resolver, err = ccr.cc.resolverBuilder.Build(ccr.cc.parsedTarget, ccr, opts)
|
||||
errCh <- err
|
||||
})
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) {
|
||||
ccr.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccr.resolver == nil {
|
||||
return
|
||||
}
|
||||
ccr.resolver.ResolveNow(o)
|
||||
})
|
||||
}
|
||||
|
||||
// close initiates async shutdown of the wrapper. To determine the wrapper has
|
||||
// finished shutting down, the channel should block on ccr.serializer.Done()
|
||||
// without cc.mu held.
|
||||
func (ccr *ccResolverWrapper) close() {
|
||||
channelz.Info(logger, ccr.cc.channelzID, "Closing the name resolver")
|
||||
ccr.mu.Lock()
|
||||
ccr.closed = true
|
||||
ccr.mu.Unlock()
|
||||
|
||||
ccr.serializer.Schedule(func(context.Context) {
|
||||
if ccr.resolver == nil {
|
||||
return
|
||||
}
|
||||
ccr.resolver.Close()
|
||||
ccr.resolver = nil
|
||||
})
|
||||
ccr.serializerCancel()
|
||||
}
|
||||
|
||||
// UpdateState is called by resolver implementations to report new state to gRPC
|
||||
// which includes addresses and service config.
|
||||
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
|
||||
ccr.cc.mu.Lock()
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
if s.Endpoints == nil {
|
||||
s.Endpoints = make([]resolver.Endpoint, 0, len(s.Addresses))
|
||||
for _, a := range s.Addresses {
|
||||
ep := resolver.Endpoint{Addresses: []resolver.Address{a}, Attributes: a.BalancerAttributes}
|
||||
ep.Addresses[0].BalancerAttributes = nil
|
||||
s.Endpoints = append(s.Endpoints, ep)
|
||||
}
|
||||
}
|
||||
ccr.addChannelzTraceEvent(s)
|
||||
ccr.curState = s
|
||||
ccr.mu.Unlock()
|
||||
return ccr.cc.updateResolverStateAndUnlock(s, nil)
|
||||
}
|
||||
|
||||
// ReportError is called by resolver implementations to report errors
|
||||
// encountered during name resolution to gRPC.
|
||||
func (ccr *ccResolverWrapper) ReportError(err error) {
|
||||
ccr.cc.mu.Lock()
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccr.mu.Unlock()
|
||||
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
|
||||
ccr.cc.updateResolverStateAndUnlock(resolver.State{}, err)
|
||||
}
|
||||
|
||||
// NewAddress is called by the resolver implementation to send addresses to
|
||||
// gRPC.
|
||||
func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
|
||||
ccr.cc.mu.Lock()
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.mu.Unlock()
|
||||
return
|
||||
}
|
||||
s := resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig}
|
||||
ccr.addChannelzTraceEvent(s)
|
||||
ccr.curState = s
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.updateResolverStateAndUnlock(s, nil)
|
||||
}
|
||||
|
||||
// ParseServiceConfig is called by resolver implementations to parse a JSON
|
||||
// representation of the service config.
|
||||
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
|
||||
return parseServiceConfig(scJSON)
|
||||
}
|
||||
|
||||
// addChannelzTraceEvent adds a channelz trace event containing the new
|
||||
// state received from resolver implementations.
|
||||
func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
|
||||
var updates []string
|
||||
var oldSC, newSC *ServiceConfig
|
||||
var oldOK, newOK bool
|
||||
if ccr.curState.ServiceConfig != nil {
|
||||
oldSC, oldOK = ccr.curState.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if s.ServiceConfig != nil {
|
||||
newSC, newOK = s.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if oldOK != newOK || (oldOK && newOK && oldSC.rawJSONString != newSC.rawJSONString) {
|
||||
updates = append(updates, "service config updated")
|
||||
}
|
||||
if len(ccr.curState.Addresses) > 0 && len(s.Addresses) == 0 {
|
||||
updates = append(updates, "resolver returned an empty address list")
|
||||
} else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 {
|
||||
updates = append(updates, "resolver returned new addresses")
|
||||
}
|
||||
channelz.Infof(logger, ccr.cc.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
|
||||
}
|
112
vendor/google.golang.org/grpc/rpc_util.go
generated
vendored
112
vendor/google.golang.org/grpc/rpc_util.go
generated
vendored
@@ -25,7 +25,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -76,8 +75,8 @@ func NewGZIPCompressorWithLevel(level int) (Compressor, error) {
|
||||
}
|
||||
return &gzipCompressor{
|
||||
pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
w, err := gzip.NewWriterLevel(ioutil.Discard, level)
|
||||
New: func() any {
|
||||
w, err := gzip.NewWriterLevel(io.Discard, level)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -143,7 +142,7 @@ func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) {
|
||||
z.Close()
|
||||
d.pool.Put(z)
|
||||
}()
|
||||
return ioutil.ReadAll(z)
|
||||
return io.ReadAll(z)
|
||||
}
|
||||
|
||||
func (d *gzipDecompressor) Type() string {
|
||||
@@ -160,6 +159,7 @@ type callInfo struct {
|
||||
contentSubtype string
|
||||
codec baseCodec
|
||||
maxRetryRPCBufferSize int
|
||||
onFinish []func(err error)
|
||||
}
|
||||
|
||||
func defaultCallInfo() *callInfo {
|
||||
@@ -296,8 +296,44 @@ func (o FailFastCallOption) before(c *callInfo) error {
|
||||
}
|
||||
func (o FailFastCallOption) after(c *callInfo, attempt *csAttempt) {}
|
||||
|
||||
// OnFinish returns a CallOption that configures a callback to be called when
|
||||
// the call completes. The error passed to the callback is the status of the
|
||||
// RPC, and may be nil. The onFinish callback provided will only be called once
|
||||
// by gRPC. This is mainly used to be used by streaming interceptors, to be
|
||||
// notified when the RPC completes along with information about the status of
|
||||
// the RPC.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func OnFinish(onFinish func(err error)) CallOption {
|
||||
return OnFinishCallOption{
|
||||
OnFinish: onFinish,
|
||||
}
|
||||
}
|
||||
|
||||
// OnFinishCallOption is CallOption that indicates a callback to be called when
|
||||
// the call completes.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type OnFinishCallOption struct {
|
||||
OnFinish func(error)
|
||||
}
|
||||
|
||||
func (o OnFinishCallOption) before(c *callInfo) error {
|
||||
c.onFinish = append(c.onFinish, o.OnFinish)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o OnFinishCallOption) after(c *callInfo, attempt *csAttempt) {}
|
||||
|
||||
// MaxCallRecvMsgSize returns a CallOption which sets the maximum message size
|
||||
// in bytes the client can receive.
|
||||
// in bytes the client can receive. If this is not set, gRPC uses the default
|
||||
// 4MB.
|
||||
func MaxCallRecvMsgSize(bytes int) CallOption {
|
||||
return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes}
|
||||
}
|
||||
@@ -320,7 +356,8 @@ func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error {
|
||||
func (o MaxRecvMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {}
|
||||
|
||||
// MaxCallSendMsgSize returns a CallOption which sets the maximum message size
|
||||
// in bytes the client can send.
|
||||
// in bytes the client can send. If this is not set, gRPC uses the default
|
||||
// `math.MaxInt32`.
|
||||
func MaxCallSendMsgSize(bytes int) CallOption {
|
||||
return MaxSendMsgSizeCallOption{MaxSendMsgSize: bytes}
|
||||
}
|
||||
@@ -540,6 +577,9 @@ type parser struct {
|
||||
// The header of a gRPC message. Find more detail at
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
|
||||
header [5]byte
|
||||
|
||||
// recvBufferPool is the pool of shared receive buffers.
|
||||
recvBufferPool SharedBufferPool
|
||||
}
|
||||
|
||||
// recvMsg reads a complete gRPC message from the stream.
|
||||
@@ -573,9 +613,7 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
|
||||
if int(length) > maxReceiveMessageSize {
|
||||
return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize)
|
||||
}
|
||||
// TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead
|
||||
// of making it for each message:
|
||||
msg = make([]byte, int(length))
|
||||
msg = p.recvBufferPool.Get(int(length))
|
||||
if _, err := p.r.Read(msg); err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
@@ -588,7 +626,7 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
|
||||
// encode serializes msg and returns a buffer containing the message, or an
|
||||
// error if it is too large to be transmitted by grpc. If msg is nil, it
|
||||
// generates an empty message.
|
||||
func encode(c baseCodec, msg interface{}) ([]byte, error) {
|
||||
func encode(c baseCodec, msg any) ([]byte, error) {
|
||||
if msg == nil { // NOTE: typed nils will not be caught by this check
|
||||
return nil, nil
|
||||
}
|
||||
@@ -655,14 +693,15 @@ func msgHeader(data, compData []byte) (hdr []byte, payload []byte) {
|
||||
return hdr, data
|
||||
}
|
||||
|
||||
func outPayload(client bool, msg interface{}, data, payload []byte, t time.Time) *stats.OutPayload {
|
||||
func outPayload(client bool, msg any, data, payload []byte, t time.Time) *stats.OutPayload {
|
||||
return &stats.OutPayload{
|
||||
Client: client,
|
||||
Payload: msg,
|
||||
Data: data,
|
||||
Length: len(data),
|
||||
WireLength: len(payload) + headerLen,
|
||||
SentTime: t,
|
||||
Client: client,
|
||||
Payload: msg,
|
||||
Data: data,
|
||||
Length: len(data),
|
||||
WireLength: len(payload) + headerLen,
|
||||
CompressedLength: len(payload),
|
||||
SentTime: t,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,17 +722,17 @@ func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool
|
||||
}
|
||||
|
||||
type payloadInfo struct {
|
||||
wireLength int // The compressed length got from wire.
|
||||
compressedLength int // The compressed length got from wire.
|
||||
uncompressedBytes []byte
|
||||
}
|
||||
|
||||
func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) ([]byte, error) {
|
||||
pf, d, err := p.recvMsg(maxReceiveMessageSize)
|
||||
pf, buf, err := p.recvMsg(maxReceiveMessageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if payInfo != nil {
|
||||
payInfo.wireLength = len(d)
|
||||
payInfo.compressedLength = len(buf)
|
||||
}
|
||||
|
||||
if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil {
|
||||
@@ -705,13 +744,13 @@ func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxRecei
|
||||
// To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor,
|
||||
// use this decompressor as the default.
|
||||
if dc != nil {
|
||||
d, err = dc.Do(bytes.NewReader(d))
|
||||
size = len(d)
|
||||
buf, err = dc.Do(bytes.NewReader(buf))
|
||||
size = len(buf)
|
||||
} else {
|
||||
d, size, err = decompress(compressor, d, maxReceiveMessageSize)
|
||||
buf, size, err = decompress(compressor, buf, maxReceiveMessageSize)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
|
||||
return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err)
|
||||
}
|
||||
if size > maxReceiveMessageSize {
|
||||
// TODO: Revisit the error code. Currently keep it consistent with java
|
||||
@@ -719,7 +758,7 @@ func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxRecei
|
||||
return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize)
|
||||
}
|
||||
}
|
||||
return d, nil
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Using compressor, decompress d, returning data and size.
|
||||
@@ -746,23 +785,25 @@ func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize
|
||||
}
|
||||
// Read from LimitReader with limit max+1. So if the underlying
|
||||
// reader is over limit, the result will be bigger than max.
|
||||
d, err = ioutil.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1))
|
||||
d, err = io.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1))
|
||||
return d, len(d), err
|
||||
}
|
||||
|
||||
// For the two compressor parameters, both should not be set, but if they are,
|
||||
// dc takes precedence over compressor.
|
||||
// TODO(dfawley): wrap the old compressor/decompressor using the new API?
|
||||
func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error {
|
||||
d, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor)
|
||||
func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m any, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error {
|
||||
buf, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.Unmarshal(d, m); err != nil {
|
||||
return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err)
|
||||
if err := c.Unmarshal(buf, m); err != nil {
|
||||
return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message: %v", err)
|
||||
}
|
||||
if payInfo != nil {
|
||||
payInfo.uncompressedBytes = d
|
||||
payInfo.uncompressedBytes = buf
|
||||
} else {
|
||||
p.recvBufferPool.Put(&buf)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -822,19 +863,22 @@ func ErrorDesc(err error) string {
|
||||
// Errorf returns nil if c is OK.
|
||||
//
|
||||
// Deprecated: use status.Errorf instead.
|
||||
func Errorf(c codes.Code, format string, a ...interface{}) error {
|
||||
func Errorf(c codes.Code, format string, a ...any) error {
|
||||
return status.Errorf(c, format, a...)
|
||||
}
|
||||
|
||||
var errContextCanceled = status.Error(codes.Canceled, context.Canceled.Error())
|
||||
var errContextDeadline = status.Error(codes.DeadlineExceeded, context.DeadlineExceeded.Error())
|
||||
|
||||
// toRPCErr converts an error into an error from the status package.
|
||||
func toRPCErr(err error) error {
|
||||
switch err {
|
||||
case nil, io.EOF:
|
||||
return err
|
||||
case context.DeadlineExceeded:
|
||||
return status.Error(codes.DeadlineExceeded, err.Error())
|
||||
return errContextDeadline
|
||||
case context.Canceled:
|
||||
return status.Error(codes.Canceled, err.Error())
|
||||
return errContextCanceled
|
||||
case io.ErrUnexpectedEOF:
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
723
vendor/google.golang.org/grpc/server.go
generated
vendored
723
vendor/google.golang.org/grpc/server.go
generated
vendored
File diff suppressed because it is too large
Load Diff
83
vendor/google.golang.org/grpc/service_config.go
generated
vendored
83
vendor/google.golang.org/grpc/service_config.go
generated
vendored
@@ -23,8 +23,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -106,8 +104,8 @@ type healthCheckConfig struct {
|
||||
|
||||
type jsonRetryPolicy struct {
|
||||
MaxAttempts int
|
||||
InitialBackoff string
|
||||
MaxBackoff string
|
||||
InitialBackoff internalserviceconfig.Duration
|
||||
MaxBackoff internalserviceconfig.Duration
|
||||
BackoffMultiplier float64
|
||||
RetryableStatusCodes []codes.Code
|
||||
}
|
||||
@@ -129,50 +127,6 @@ type retryThrottlingPolicy struct {
|
||||
TokenRatio float64
|
||||
}
|
||||
|
||||
func parseDuration(s *string) (*time.Duration, error) {
|
||||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if !strings.HasSuffix(*s, "s") {
|
||||
return nil, fmt.Errorf("malformed duration %q", *s)
|
||||
}
|
||||
ss := strings.SplitN((*s)[:len(*s)-1], ".", 3)
|
||||
if len(ss) > 2 {
|
||||
return nil, fmt.Errorf("malformed duration %q", *s)
|
||||
}
|
||||
// hasDigits is set if either the whole or fractional part of the number is
|
||||
// present, since both are optional but one is required.
|
||||
hasDigits := false
|
||||
var d time.Duration
|
||||
if len(ss[0]) > 0 {
|
||||
i, err := strconv.ParseInt(ss[0], 10, 32)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
|
||||
}
|
||||
d = time.Duration(i) * time.Second
|
||||
hasDigits = true
|
||||
}
|
||||
if len(ss) == 2 && len(ss[1]) > 0 {
|
||||
if len(ss[1]) > 9 {
|
||||
return nil, fmt.Errorf("malformed duration %q", *s)
|
||||
}
|
||||
f, err := strconv.ParseInt(ss[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
|
||||
}
|
||||
for i := 9; i > len(ss[1]); i-- {
|
||||
f *= 10
|
||||
}
|
||||
d += time.Duration(f)
|
||||
hasDigits = true
|
||||
}
|
||||
if !hasDigits {
|
||||
return nil, fmt.Errorf("malformed duration %q", *s)
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
type jsonName struct {
|
||||
Service string
|
||||
Method string
|
||||
@@ -201,7 +155,7 @@ func (j jsonName) generatePath() (string, error) {
|
||||
type jsonMC struct {
|
||||
Name *[]jsonName
|
||||
WaitForReady *bool
|
||||
Timeout *string
|
||||
Timeout *internalserviceconfig.Duration
|
||||
MaxRequestMessageBytes *int64
|
||||
MaxResponseMessageBytes *int64
|
||||
RetryPolicy *jsonRetryPolicy
|
||||
@@ -226,7 +180,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
|
||||
var rsc jsonSC
|
||||
err := json.Unmarshal([]byte(js), &rsc)
|
||||
if err != nil {
|
||||
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
|
||||
logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
|
||||
return &serviceconfig.ParseResult{Err: err}
|
||||
}
|
||||
sc := ServiceConfig{
|
||||
@@ -252,18 +206,13 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
|
||||
if m.Name == nil {
|
||||
continue
|
||||
}
|
||||
d, err := parseDuration(m.Timeout)
|
||||
if err != nil {
|
||||
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
|
||||
return &serviceconfig.ParseResult{Err: err}
|
||||
}
|
||||
|
||||
mc := MethodConfig{
|
||||
WaitForReady: m.WaitForReady,
|
||||
Timeout: d,
|
||||
Timeout: (*time.Duration)(m.Timeout),
|
||||
}
|
||||
if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
|
||||
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
|
||||
logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
|
||||
return &serviceconfig.ParseResult{Err: err}
|
||||
}
|
||||
if m.MaxRequestMessageBytes != nil {
|
||||
@@ -283,13 +232,13 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
|
||||
for i, n := range *m.Name {
|
||||
path, err := n.generatePath()
|
||||
if err != nil {
|
||||
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to methodConfig[%d]: %v", js, i, err)
|
||||
logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err)
|
||||
return &serviceconfig.ParseResult{Err: err}
|
||||
}
|
||||
|
||||
if _, ok := paths[path]; ok {
|
||||
err = errDuplicatedName
|
||||
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to methodConfig[%d]: %v", js, i, err)
|
||||
logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err)
|
||||
return &serviceconfig.ParseResult{Err: err}
|
||||
}
|
||||
paths[path] = struct{}{}
|
||||
@@ -312,18 +261,10 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol
|
||||
if jrp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
ib, err := parseDuration(&jrp.InitialBackoff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mb, err := parseDuration(&jrp.MaxBackoff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if jrp.MaxAttempts <= 1 ||
|
||||
*ib <= 0 ||
|
||||
*mb <= 0 ||
|
||||
jrp.InitialBackoff <= 0 ||
|
||||
jrp.MaxBackoff <= 0 ||
|
||||
jrp.BackoffMultiplier <= 0 ||
|
||||
len(jrp.RetryableStatusCodes) == 0 {
|
||||
logger.Warningf("grpc: ignoring retry policy %v due to illegal configuration", jrp)
|
||||
@@ -332,8 +273,8 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol
|
||||
|
||||
rp := &internalserviceconfig.RetryPolicy{
|
||||
MaxAttempts: jrp.MaxAttempts,
|
||||
InitialBackoff: *ib,
|
||||
MaxBackoff: *mb,
|
||||
InitialBackoff: time.Duration(jrp.InitialBackoff),
|
||||
MaxBackoff: time.Duration(jrp.MaxBackoff),
|
||||
BackoffMultiplier: jrp.BackoffMultiplier,
|
||||
RetryableStatusCodes: make(map[codes.Code]bool),
|
||||
}
|
||||
|
154
vendor/google.golang.org/grpc/shared_buffer_pool.go
generated
vendored
Normal file
154
vendor/google.golang.org/grpc/shared_buffer_pool.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import "sync"
|
||||
|
||||
// SharedBufferPool is a pool of buffers that can be shared, resulting in
|
||||
// decreased memory allocation. Currently, in gRPC-go, it is only utilized
|
||||
// for parsing incoming messages.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type SharedBufferPool interface {
|
||||
// Get returns a buffer with specified length from the pool.
|
||||
//
|
||||
// The returned byte slice may be not zero initialized.
|
||||
Get(length int) []byte
|
||||
|
||||
// Put returns a buffer to the pool.
|
||||
Put(*[]byte)
|
||||
}
|
||||
|
||||
// NewSharedBufferPool creates a simple SharedBufferPool with buckets
|
||||
// of different sizes to optimize memory usage. This prevents the pool from
|
||||
// wasting large amounts of memory, even when handling messages of varying sizes.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func NewSharedBufferPool() SharedBufferPool {
|
||||
return &simpleSharedBufferPool{
|
||||
pools: [poolArraySize]simpleSharedBufferChildPool{
|
||||
newBytesPool(level0PoolMaxSize),
|
||||
newBytesPool(level1PoolMaxSize),
|
||||
newBytesPool(level2PoolMaxSize),
|
||||
newBytesPool(level3PoolMaxSize),
|
||||
newBytesPool(level4PoolMaxSize),
|
||||
newBytesPool(0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// simpleSharedBufferPool is a simple implementation of SharedBufferPool.
|
||||
type simpleSharedBufferPool struct {
|
||||
pools [poolArraySize]simpleSharedBufferChildPool
|
||||
}
|
||||
|
||||
func (p *simpleSharedBufferPool) Get(size int) []byte {
|
||||
return p.pools[p.poolIdx(size)].Get(size)
|
||||
}
|
||||
|
||||
func (p *simpleSharedBufferPool) Put(bs *[]byte) {
|
||||
p.pools[p.poolIdx(cap(*bs))].Put(bs)
|
||||
}
|
||||
|
||||
func (p *simpleSharedBufferPool) poolIdx(size int) int {
|
||||
switch {
|
||||
case size <= level0PoolMaxSize:
|
||||
return level0PoolIdx
|
||||
case size <= level1PoolMaxSize:
|
||||
return level1PoolIdx
|
||||
case size <= level2PoolMaxSize:
|
||||
return level2PoolIdx
|
||||
case size <= level3PoolMaxSize:
|
||||
return level3PoolIdx
|
||||
case size <= level4PoolMaxSize:
|
||||
return level4PoolIdx
|
||||
default:
|
||||
return levelMaxPoolIdx
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
level0PoolMaxSize = 16 // 16 B
|
||||
level1PoolMaxSize = level0PoolMaxSize * 16 // 256 B
|
||||
level2PoolMaxSize = level1PoolMaxSize * 16 // 4 KB
|
||||
level3PoolMaxSize = level2PoolMaxSize * 16 // 64 KB
|
||||
level4PoolMaxSize = level3PoolMaxSize * 16 // 1 MB
|
||||
)
|
||||
|
||||
const (
|
||||
level0PoolIdx = iota
|
||||
level1PoolIdx
|
||||
level2PoolIdx
|
||||
level3PoolIdx
|
||||
level4PoolIdx
|
||||
levelMaxPoolIdx
|
||||
poolArraySize
|
||||
)
|
||||
|
||||
type simpleSharedBufferChildPool interface {
|
||||
Get(size int) []byte
|
||||
Put(any)
|
||||
}
|
||||
|
||||
type bufferPool struct {
|
||||
sync.Pool
|
||||
|
||||
defaultSize int
|
||||
}
|
||||
|
||||
func (p *bufferPool) Get(size int) []byte {
|
||||
bs := p.Pool.Get().(*[]byte)
|
||||
|
||||
if cap(*bs) < size {
|
||||
p.Pool.Put(bs)
|
||||
|
||||
return make([]byte, size)
|
||||
}
|
||||
|
||||
return (*bs)[:size]
|
||||
}
|
||||
|
||||
func newBytesPool(size int) simpleSharedBufferChildPool {
|
||||
return &bufferPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() any {
|
||||
bs := make([]byte, size)
|
||||
return &bs
|
||||
},
|
||||
},
|
||||
defaultSize: size,
|
||||
}
|
||||
}
|
||||
|
||||
// nopBufferPool is a buffer pool just makes new buffer without pooling.
|
||||
type nopBufferPool struct {
|
||||
}
|
||||
|
||||
func (nopBufferPool) Get(length int) []byte {
|
||||
return make([]byte, length)
|
||||
}
|
||||
|
||||
func (nopBufferPool) Put(*[]byte) {
|
||||
}
|
36
vendor/google.golang.org/grpc/stats/stats.go
generated
vendored
36
vendor/google.golang.org/grpc/stats/stats.go
generated
vendored
@@ -59,18 +59,36 @@ func (s *Begin) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *Begin) isRPCStats() {}
|
||||
|
||||
// PickerUpdated indicates that the LB policy provided a new picker while the
|
||||
// RPC was waiting for one.
|
||||
type PickerUpdated struct{}
|
||||
|
||||
// IsClient indicates if the stats information is from client side. Only Client
|
||||
// Side interfaces with a Picker, thus always returns true.
|
||||
func (*PickerUpdated) IsClient() bool { return true }
|
||||
|
||||
func (*PickerUpdated) isRPCStats() {}
|
||||
|
||||
// InPayload contains the information for an incoming payload.
|
||||
type InPayload struct {
|
||||
// Client is true if this InPayload is from client side.
|
||||
Client bool
|
||||
// Payload is the payload with original type.
|
||||
Payload interface{}
|
||||
Payload any
|
||||
// Data is the serialized message payload.
|
||||
Data []byte
|
||||
// Length is the length of uncompressed data.
|
||||
|
||||
// Length is the size of the uncompressed payload data. Does not include any
|
||||
// framing (gRPC or HTTP/2).
|
||||
Length int
|
||||
// WireLength is the length of data on wire (compressed, signed, encrypted).
|
||||
// CompressedLength is the size of the compressed payload data. Does not
|
||||
// include any framing (gRPC or HTTP/2). Same as Length if compression not
|
||||
// enabled.
|
||||
CompressedLength int
|
||||
// WireLength is the size of the compressed payload data plus gRPC framing.
|
||||
// Does not include HTTP/2 framing.
|
||||
WireLength int
|
||||
|
||||
// RecvTime is the time when the payload is received.
|
||||
RecvTime time.Time
|
||||
}
|
||||
@@ -126,12 +144,18 @@ type OutPayload struct {
|
||||
// Client is true if this OutPayload is from client side.
|
||||
Client bool
|
||||
// Payload is the payload with original type.
|
||||
Payload interface{}
|
||||
Payload any
|
||||
// Data is the serialized message payload.
|
||||
Data []byte
|
||||
// Length is the length of uncompressed data.
|
||||
// Length is the size of the uncompressed payload data. Does not include any
|
||||
// framing (gRPC or HTTP/2).
|
||||
Length int
|
||||
// WireLength is the length of data on wire (compressed, signed, encrypted).
|
||||
// CompressedLength is the size of the compressed payload data. Does not
|
||||
// include any framing (gRPC or HTTP/2). Same as Length if compression not
|
||||
// enabled.
|
||||
CompressedLength int
|
||||
// WireLength is the size of the compressed payload data plus gRPC framing.
|
||||
// Does not include HTTP/2 framing.
|
||||
WireLength int
|
||||
// SentTime is the time when the payload is sent.
|
||||
SentTime time.Time
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user