mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
36
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
36
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
@ -27,16 +27,42 @@ import (
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// Logger is the global binary logger for the binary. One of this should be
|
||||
// Logger is the global binary logger. It can be used to get binary logger for
|
||||
// each method.
|
||||
type Logger interface {
|
||||
getMethodLogger(methodName string) *MethodLogger
|
||||
}
|
||||
|
||||
// binLogger is the global binary logger for the binary. One of this should be
|
||||
// built at init time from the configuration (environment varialbe or flags).
|
||||
//
|
||||
// It is used to get a methodLogger for each individual method.
|
||||
var Logger *logger
|
||||
var binLogger Logger
|
||||
|
||||
// SetLogger sets the binarg logger.
|
||||
//
|
||||
// Only call this at init time.
|
||||
func SetLogger(l Logger) {
|
||||
binLogger = l
|
||||
}
|
||||
|
||||
// GetMethodLogger returns the methodLogger for the given methodName.
|
||||
//
|
||||
// methodName should be in the format of "/service/method".
|
||||
//
|
||||
// Each methodLogger returned by this method is a new instance. This is to
|
||||
// generate sequence id within the call.
|
||||
func GetMethodLogger(methodName string) *MethodLogger {
|
||||
if binLogger == nil {
|
||||
return nil
|
||||
}
|
||||
return binLogger.getMethodLogger(methodName)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const envStr = "GRPC_BINARY_LOG_FILTER"
|
||||
configStr := os.Getenv(envStr)
|
||||
Logger = newLoggerFromConfigString(configStr)
|
||||
binLogger = NewLoggerFromConfigString(configStr)
|
||||
}
|
||||
|
||||
type methodLoggerConfig struct {
|
||||
@ -113,13 +139,13 @@ func (l *logger) setBlacklist(method string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMethodLogger returns the methodLogger for the given methodName.
|
||||
// getMethodLogger returns the methodLogger for the given methodName.
|
||||
//
|
||||
// methodName should be in the format of "/service/method".
|
||||
//
|
||||
// Each methodLogger returned by this method is a new instance. This is to
|
||||
// generate sequence id within the call.
|
||||
func (l *logger) GetMethodLogger(methodName string) *MethodLogger {
|
||||
func (l *logger) getMethodLogger(methodName string) *MethodLogger {
|
||||
s, m, err := parseMethodName(methodName)
|
||||
if err != nil {
|
||||
grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
|
||||
|
1044
vendor/google.golang.org/grpc/internal/binarylog/binarylog_end2end_test.go
generated
vendored
Normal file
1044
vendor/google.golang.org/grpc/internal/binarylog/binarylog_end2end_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
vendor/google.golang.org/grpc/internal/binarylog/binarylog_test.go
generated
vendored
8
vendor/google.golang.org/grpc/internal/binarylog/binarylog_test.go
generated
vendored
@ -78,12 +78,12 @@ func TestGetMethodLogger(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
l := newLoggerFromConfigString(tc.in)
|
||||
l := NewLoggerFromConfigString(tc.in)
|
||||
if l == nil {
|
||||
t.Errorf("in: %q, failed to create logger from config string", tc.in)
|
||||
continue
|
||||
}
|
||||
ml := l.GetMethodLogger(tc.method)
|
||||
ml := l.getMethodLogger(tc.method)
|
||||
if ml == nil {
|
||||
t.Errorf("in: %q, method logger is nil, want non-nil", tc.in)
|
||||
continue
|
||||
@ -134,12 +134,12 @@ func TestGetMethodLoggerOff(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
l := newLoggerFromConfigString(tc.in)
|
||||
l := NewLoggerFromConfigString(tc.in)
|
||||
if l == nil {
|
||||
t.Errorf("in: %q, failed to create logger from config string", tc.in)
|
||||
continue
|
||||
}
|
||||
ml := l.GetMethodLogger(tc.method)
|
||||
ml := l.getMethodLogger(tc.method)
|
||||
if ml != nil {
|
||||
t.Errorf("in: %q, method logger is non-nil, want nil", tc.in)
|
||||
}
|
||||
|
42
vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
generated
vendored
Normal file
42
vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file contains exported variables/functions that are exported for testing
|
||||
// only.
|
||||
//
|
||||
// An ideal way for this would be to put those in a *_test.go but in binarylog
|
||||
// package. But this doesn't work with staticcheck with go module. Error was:
|
||||
// "MdToMetadataProto not declared by package binarylog". This could be caused
|
||||
// by the way staticcheck looks for files for a certain package, which doesn't
|
||||
// support *_test.go files.
|
||||
//
|
||||
// Move those to binary_test.go when staticcheck is fixed.
|
||||
|
||||
package binarylog
|
||||
|
||||
var (
|
||||
// AllLogger is a logger that logs all headers/messages for all RPCs. It's
|
||||
// for testing only.
|
||||
AllLogger = NewLoggerFromConfigString("*")
|
||||
// MdToMetadataProto converts metadata to a binary logging proto message.
|
||||
// It's for testing only.
|
||||
MdToMetadataProto = mdToMetadataProto
|
||||
// AddrToProto converts an address to a binary logging proto message. It's
|
||||
// for testing only.
|
||||
AddrToProto = addrToProto
|
||||
)
|
8
vendor/google.golang.org/grpc/internal/binarylog/env_config.go
generated
vendored
8
vendor/google.golang.org/grpc/internal/binarylog/env_config.go
generated
vendored
@ -28,7 +28,8 @@ import (
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// newLoggerFromConfigString reads the string and build a logger.
|
||||
// NewLoggerFromConfigString reads the string and build a logger. It can be used
|
||||
// to build a new logger and assign it to binarylog.Logger.
|
||||
//
|
||||
// Example filter config strings:
|
||||
// - "" Nothing will be logged
|
||||
@ -43,7 +44,10 @@ import (
|
||||
//
|
||||
// If two configs exist for one certain method or service, the one specified
|
||||
// later overrides the privous config.
|
||||
func newLoggerFromConfigString(s string) *logger {
|
||||
func NewLoggerFromConfigString(s string) Logger {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
l := newEmptyLogger()
|
||||
methods := strings.Split(s, ",")
|
||||
for _, method := range methods {
|
||||
|
4
vendor/google.golang.org/grpc/internal/binarylog/env_config_test.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/binarylog/env_config_test.go
generated
vendored
@ -34,7 +34,7 @@ func TestNewLoggerFromConfigString(t *testing.T) {
|
||||
fullM2 = s1 + "/" + m2
|
||||
)
|
||||
c := fmt.Sprintf("*{h:1;m:2},%s{h},%s{m},%s{h;m}", s1+"/*", fullM1, fullM2)
|
||||
l := newLoggerFromConfigString(c)
|
||||
l := NewLoggerFromConfigString(c).(*logger)
|
||||
|
||||
if l.all.hdr != 1 || l.all.msg != 2 {
|
||||
t.Errorf("l.all = %#v, want headerLen: 1, messageLen: 2", l.all)
|
||||
@ -83,7 +83,7 @@ func TestNewLoggerFromConfigStringInvalid(t *testing.T) {
|
||||
"*,*{h:1;m:1}",
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
l := newLoggerFromConfigString(tc)
|
||||
l := NewLoggerFromConfigString(tc)
|
||||
if l != nil {
|
||||
t.Errorf("With config %q, want logger %v, got %v", tc, nil, l)
|
||||
}
|
||||
|
10
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
10
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
@ -206,8 +206,8 @@ func (c *ServerHeader) toProto() *pb.GrpcLogEntry {
|
||||
// ClientMessage configs the binary log entry to be a ClientMessage entry.
|
||||
type ClientMessage struct {
|
||||
OnClientSide bool
|
||||
// Message should only be a proto.Message. Could add support for other
|
||||
// message types in the future.
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message interface{}
|
||||
}
|
||||
|
||||
@ -246,8 +246,8 @@ func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
|
||||
// ServerMessage configs the binary log entry to be a ServerMessage entry.
|
||||
type ServerMessage struct {
|
||||
OnClientSide bool
|
||||
// Message should only be a proto.Message. Could add support for other
|
||||
// message types in the future.
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message interface{}
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ func (c *Cancel) toProto() *pb.GrpcLogEntry {
|
||||
// omitted.
|
||||
func metadataKeyOmit(key string) bool {
|
||||
switch key {
|
||||
case "lb-token", ":path", ":authority", "content-encoding", "user-agent", "te":
|
||||
case "lb-token", ":path", ":authority", "content-encoding", "content-type", "user-agent", "te":
|
||||
return true
|
||||
case "grpc-trace-bin": // grpc-trace-bin is special because it's visiable to users.
|
||||
return false
|
||||
|
4
vendor/google.golang.org/grpc/internal/binarylog/method_logger_test.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/binarylog/method_logger_test.go
generated
vendored
@ -37,7 +37,7 @@ func TestLog(t *testing.T) {
|
||||
ml := newMethodLogger(10, 10)
|
||||
// Set sink to testing buffer.
|
||||
buf := bytes.NewBuffer(nil)
|
||||
ml.sink = NewWriterSink(buf)
|
||||
ml.sink = newWriterSink(buf)
|
||||
|
||||
addr := "1.2.3.4"
|
||||
port := 790
|
||||
@ -337,7 +337,7 @@ func TestLog(t *testing.T) {
|
||||
tc.want.SequenceIdWithinCall = uint64(i + 1)
|
||||
ml.Log(tc.config)
|
||||
inSink := new(pb.GrpcLogEntry)
|
||||
if err := proto.Unmarshal(buf.Bytes(), inSink); err != nil {
|
||||
if err := proto.Unmarshal(buf.Bytes()[4:], inSink); err != nil {
|
||||
t.Errorf("failed to unmarshal bytes in sink to proto: %v", err)
|
||||
continue
|
||||
}
|
||||
|
110
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
110
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
@ -19,7 +19,13 @@
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
@ -34,20 +40,34 @@ var (
|
||||
//
|
||||
// Not thread safe. Only set during initialization.
|
||||
func SetDefaultSink(s Sink) {
|
||||
if defaultSink != nil {
|
||||
defaultSink.Close()
|
||||
}
|
||||
defaultSink = s
|
||||
}
|
||||
|
||||
// Sink writes log entry into the binary log sink.
|
||||
type Sink interface {
|
||||
Write(*pb.GrpcLogEntry)
|
||||
// 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
|
||||
// Close will be called when the Sink is replaced by a new Sink.
|
||||
Close() error
|
||||
}
|
||||
|
||||
type noopSink struct{}
|
||||
|
||||
func (ns *noopSink) Write(*pb.GrpcLogEntry) {}
|
||||
func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil }
|
||||
func (ns *noopSink) Close() error { return nil }
|
||||
|
||||
// NewWriterSink creates a binary log sink with the given writer.
|
||||
func NewWriterSink(w io.Writer) Sink {
|
||||
// newWriterSink creates a binary log sink with the given writer.
|
||||
//
|
||||
// Write() marshalls the proto message and writes it to the given writer. Each
|
||||
// message is prefixed with a 4 byte big endian unsigned integer as the length.
|
||||
//
|
||||
// No buffer is done, Close() doesn't try to close the writer.
|
||||
func newWriterSink(w io.Writer) *writerSink {
|
||||
return &writerSink{out: w}
|
||||
}
|
||||
|
||||
@ -55,10 +75,88 @@ type writerSink struct {
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func (fs *writerSink) Write(e *pb.GrpcLogEntry) {
|
||||
func (ws *writerSink) Write(e *pb.GrpcLogEntry) error {
|
||||
b, err := proto.Marshal(e)
|
||||
if err != nil {
|
||||
grpclog.Infof("binary logging: failed to marshal proto message: %v", err)
|
||||
}
|
||||
fs.out.Write(b)
|
||||
hdr := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(hdr, uint32(len(b)))
|
||||
if _, err := ws.out.Write(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := ws.out.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ws *writerSink) Close() error { return nil }
|
||||
|
||||
type bufWriteCloserSink struct {
|
||||
mu sync.Mutex
|
||||
closer io.Closer
|
||||
out *writerSink // out is built on buf.
|
||||
buf *bufio.Writer // buf is kept for flush.
|
||||
|
||||
writeStartOnce sync.Once
|
||||
writeTicker *time.Ticker
|
||||
}
|
||||
|
||||
func (fs *bufWriteCloserSink) Write(e *pb.GrpcLogEntry) error {
|
||||
// Start the write loop when Write is called.
|
||||
fs.writeStartOnce.Do(fs.startFlushGoroutine)
|
||||
fs.mu.Lock()
|
||||
if err := fs.out.Write(e); err != nil {
|
||||
fs.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
fs.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
bufFlushDuration = 60 * time.Second
|
||||
)
|
||||
|
||||
func (fs *bufWriteCloserSink) startFlushGoroutine() {
|
||||
fs.writeTicker = time.NewTicker(bufFlushDuration)
|
||||
go func() {
|
||||
for range fs.writeTicker.C {
|
||||
fs.mu.Lock()
|
||||
fs.buf.Flush()
|
||||
fs.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (fs *bufWriteCloserSink) Close() error {
|
||||
if fs.writeTicker != nil {
|
||||
fs.writeTicker.Stop()
|
||||
}
|
||||
fs.mu.Lock()
|
||||
fs.buf.Flush()
|
||||
fs.closer.Close()
|
||||
fs.out.Close()
|
||||
fs.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func newBufWriteCloserSink(o io.WriteCloser) Sink {
|
||||
bufW := bufio.NewWriter(o)
|
||||
return &bufWriteCloserSink{
|
||||
closer: o,
|
||||
out: newWriterSink(bufW),
|
||||
buf: bufW,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTempFileSink creates a temp file and returns a Sink that writes to this
|
||||
// file.
|
||||
func NewTempFileSink() (Sink, error) {
|
||||
tempFile, err := ioutil.TempFile("/tmp", "grpcgo_binarylog_*.txt")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create temp file: %v", err)
|
||||
}
|
||||
return newBufWriteCloserSink(tempFile), nil
|
||||
}
|
||||
|
12
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
12
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
@ -558,7 +558,7 @@ func (c *channelMap) GetServerSockets(id int64, startID int64) ([]*SocketMetric,
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
|
||||
count := 0
|
||||
var end bool
|
||||
for i, v := range ids[idx:] {
|
||||
@ -601,8 +601,11 @@ func (c *channelMap) GetChannel(id int64) *ChannelMetric {
|
||||
}
|
||||
cm.NestedChans = copyMap(cn.nestedChans)
|
||||
cm.SubChans = copyMap(cn.subChans)
|
||||
// cn.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of cn.c when
|
||||
// holding the lock to prevent potential data race.
|
||||
chanCopy := cn.c
|
||||
c.mu.RUnlock()
|
||||
cm.ChannelData = cn.c.ChannelzMetric()
|
||||
cm.ChannelData = chanCopy.ChannelzMetric()
|
||||
cm.ID = cn.id
|
||||
cm.RefName = cn.refName
|
||||
cm.Trace = cn.trace.dumpData()
|
||||
@ -620,8 +623,11 @@ func (c *channelMap) GetSubChannel(id int64) *SubChannelMetric {
|
||||
return nil
|
||||
}
|
||||
cm.Sockets = copyMap(sc.sockets)
|
||||
// sc.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of sc.c when
|
||||
// holding the lock to prevent potential data race.
|
||||
chanCopy := sc.c
|
||||
c.mu.RUnlock()
|
||||
cm.ChannelData = sc.c.ChannelzMetric()
|
||||
cm.ChannelData = chanCopy.ChannelzMetric()
|
||||
cm.ID = sc.id
|
||||
cm.RefName = sc.refName
|
||||
cm.Trace = sc.trace.dumpData()
|
||||
|
2
vendor/google.golang.org/grpc/internal/channelz/types_linux.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/channelz/types_linux.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// +build !appengine,go1.7
|
||||
// +build !appengine
|
||||
|
||||
/*
|
||||
*
|
||||
|
2
vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// +build !linux appengine !go1.7
|
||||
// +build !linux appengine
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build linux,go1.9,!appengine
|
||||
// +build linux,!appengine
|
||||
|
||||
/*
|
||||
*
|
@ -1,4 +1,4 @@
|
||||
// +build !linux !go1.9 appengine
|
||||
// +build !linux appengine
|
||||
|
||||
/*
|
||||
*
|
38
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
38
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
@ -25,11 +25,45 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
prefix = "GRPC_GO_"
|
||||
retryStr = prefix + "RETRY"
|
||||
prefix = "GRPC_GO_"
|
||||
retryStr = prefix + "RETRY"
|
||||
requireHandshakeStr = prefix + "REQUIRE_HANDSHAKE"
|
||||
)
|
||||
|
||||
// RequireHandshakeSetting describes the settings for handshaking.
|
||||
type RequireHandshakeSetting int
|
||||
|
||||
const (
|
||||
// RequireHandshakeHybrid (default, deprecated) indicates to wait for
|
||||
// handshake before considering a connection ready, but wait before
|
||||
// considering successful.
|
||||
RequireHandshakeHybrid RequireHandshakeSetting = iota
|
||||
// RequireHandshakeOn (default after the 1.17 release) indicates to wait
|
||||
// for handshake before considering a connection ready/successful.
|
||||
RequireHandshakeOn
|
||||
// RequireHandshakeOff indicates to not wait for handshake before
|
||||
// considering a connection ready/successful.
|
||||
RequireHandshakeOff
|
||||
)
|
||||
|
||||
var (
|
||||
// Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on".
|
||||
Retry = strings.EqualFold(os.Getenv(retryStr), "on")
|
||||
// RequireHandshake is set based upon the GRPC_GO_REQUIRE_HANDSHAKE
|
||||
// environment variable.
|
||||
//
|
||||
// Will be removed after the 1.18 release.
|
||||
RequireHandshake RequireHandshakeSetting
|
||||
)
|
||||
|
||||
func init() {
|
||||
switch strings.ToLower(os.Getenv(requireHandshakeStr)) {
|
||||
case "on":
|
||||
RequireHandshake = RequireHandshakeOn
|
||||
case "off":
|
||||
RequireHandshake = RequireHandshakeOff
|
||||
case "hybrid":
|
||||
// Will be removed after the 1.17 release.
|
||||
RequireHandshake = RequireHandshakeHybrid
|
||||
}
|
||||
}
|
||||
|
18
vendor/google.golang.org/grpc/internal/grpcsync/event.go
generated
vendored
18
vendor/google.golang.org/grpc/internal/grpcsync/event.go
generated
vendored
@ -20,12 +20,16 @@
|
||||
// the sync package.
|
||||
package grpcsync
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Event represents a one-time event that may occur in the future.
|
||||
type Event struct {
|
||||
c chan struct{}
|
||||
o sync.Once
|
||||
fired int32
|
||||
c chan struct{}
|
||||
o sync.Once
|
||||
}
|
||||
|
||||
// Fire causes e to complete. It is safe to call multiple times, and
|
||||
@ -34,6 +38,7 @@ type Event struct {
|
||||
func (e *Event) Fire() bool {
|
||||
ret := false
|
||||
e.o.Do(func() {
|
||||
atomic.StoreInt32(&e.fired, 1)
|
||||
close(e.c)
|
||||
ret = true
|
||||
})
|
||||
@ -47,12 +52,7 @@ func (e *Event) Done() <-chan struct{} {
|
||||
|
||||
// HasFired returns true if Fire has been called.
|
||||
func (e *Event) HasFired() bool {
|
||||
select {
|
||||
case <-e.c:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return atomic.LoadInt32(&e.fired) == 1
|
||||
}
|
||||
|
||||
// NewEvent returns a new, ready-to-use Event.
|
||||
|
2
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
@ -20,7 +20,7 @@
|
||||
// symbols to avoid circular dependencies.
|
||||
package internal
|
||||
|
||||
import "golang.org/x/net/context"
|
||||
import "context"
|
||||
|
||||
var (
|
||||
// WithContextDialer is exported by clientconn.go
|
||||
|
49
vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
generated
vendored
49
vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// +build !appengine,go1.7
|
||||
// +build !appengine
|
||||
|
||||
/*
|
||||
*
|
||||
@ -23,7 +23,10 @@
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
@ -65,3 +68,47 @@ func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
|
||||
|
||||
return uTimeElapsed, sTimeElapsed
|
||||
}
|
||||
|
||||
// SetTCPUserTimeout sets the TCP user timeout on a connection's socket
|
||||
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
|
||||
tcpconn, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
// not a TCP connection. exit early
|
||||
return nil
|
||||
}
|
||||
rawConn, err := tcpconn.SyscallConn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting raw connection: %v", err)
|
||||
}
|
||||
err = rawConn.Control(func(fd uintptr) {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting option on socket: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTCPUserTimeout gets the TCP user timeout on a connection's socket
|
||||
func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
|
||||
tcpconn, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
|
||||
return
|
||||
}
|
||||
rawConn, err := tcpconn.SyscallConn()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error getting raw connection: %v", err)
|
||||
return
|
||||
}
|
||||
err = rawConn.Control(func(fd uintptr) {
|
||||
opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)
|
||||
})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error getting option on socket: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
20
vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
generated
vendored
20
vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// +build !linux appengine !go1.7
|
||||
// +build !linux appengine
|
||||
|
||||
/*
|
||||
*
|
||||
@ -20,7 +20,12 @@
|
||||
|
||||
package syscall
|
||||
|
||||
import "google.golang.org/grpc/grpclog"
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
grpclog.Info("CPU time info is unavailable on non-linux or appengine environment.")
|
||||
@ -45,3 +50,14 @@ func GetRusage() (rusage *Rusage) {
|
||||
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// SetTCPUserTimeout is a no-op function under non-linux or appengine environments
|
||||
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTCPUserTimeout is a no-op function under non-linux or appengine environments
|
||||
// a negative return value indicates the operation is not supported
|
||||
func GetTCPUserTimeout(conn net.Conn) (int, error) {
|
||||
return -1, nil
|
||||
}
|
||||
|
1
vendor/google.golang.org/grpc/internal/testutils/pipe_listener.go
generated
vendored
1
vendor/google.golang.org/grpc/internal/testutils/pipe_listener.go
generated
vendored
@ -16,6 +16,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// Package testutils contains testing helpers.
|
||||
package testutils
|
||||
|
||||
import (
|
||||
|
7
vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
generated
vendored
7
vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
generated
vendored
@ -24,9 +24,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// bdpLimit is the maximum value the flow control windows
|
||||
// will be increased to.
|
||||
bdpLimit = (1 << 20) * 4
|
||||
// bdpLimit is the maximum value the flow control windows will be increased
|
||||
// to. TCP typically limits this to 4MB, but some systems go up to 16MB.
|
||||
// Since this is only a limit, it is safe to make it optimistic.
|
||||
bdpLimit = (1 << 20) * 16
|
||||
// alpha is a constant factor used to keep a moving average
|
||||
// of RTTs.
|
||||
alpha = 0.9
|
||||
|
52
vendor/google.golang.org/grpc/internal/transport/go16.go
generated
vendored
52
vendor/google.golang.org/grpc/internal/transport/go16.go
generated
vendored
@ -1,52 +0,0 @@
|
||||
// +build go1.6,!go1.7
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// dialContext connects to the address on the named network.
|
||||
func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
|
||||
}
|
||||
|
||||
// ContextErr converts the error from context package into a status error.
|
||||
func ContextErr(err error) error {
|
||||
switch err {
|
||||
case context.DeadlineExceeded:
|
||||
return status.Error(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled:
|
||||
return status.Error(codes.Canceled, err.Error())
|
||||
}
|
||||
return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
|
||||
}
|
||||
|
||||
// contextFromRequest returns a background context.
|
||||
func contextFromRequest(r *http.Request) context.Context {
|
||||
return context.Background()
|
||||
}
|
53
vendor/google.golang.org/grpc/internal/transport/go17.go
generated
vendored
53
vendor/google.golang.org/grpc/internal/transport/go17.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
// +build go1.7
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
netctx "golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// dialContext connects to the address on the named network.
|
||||
func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
}
|
||||
|
||||
// ContextErr converts the error from context package into a status error.
|
||||
func ContextErr(err error) error {
|
||||
switch err {
|
||||
case context.DeadlineExceeded, netctx.DeadlineExceeded:
|
||||
return status.Error(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled, netctx.Canceled:
|
||||
return status.Error(codes.Canceled, err.Error())
|
||||
}
|
||||
return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
|
||||
}
|
||||
|
||||
// contextFromRequest returns a context from the HTTP Request.
|
||||
func contextFromRequest(r *http.Request) context.Context {
|
||||
return r.Context()
|
||||
}
|
4
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
@ -24,6 +24,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -34,7 +35,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/http2"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@ -307,7 +307,7 @@ func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
|
||||
func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
|
||||
// With this transport type there will be exactly 1 stream: this HTTP request.
|
||||
|
||||
ctx := contextFromRequest(ht.req)
|
||||
ctx := ht.req.Context()
|
||||
var cancel context.CancelFunc
|
||||
if ht.timeoutSet {
|
||||
ctx, cancel = context.WithTimeout(ctx, ht.timeout)
|
||||
|
2
vendor/google.golang.org/grpc/internal/transport/handler_server_test.go
generated
vendored
2
vendor/google.golang.org/grpc/internal/transport/handler_server_test.go
generated
vendored
@ -19,6 +19,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -32,7 +33,6 @@ import (
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
dpb "github.com/golang/protobuf/ptypes/duration"
|
||||
"golang.org/x/net/context"
|
||||
epb "google.golang.org/genproto/googleapis/rpc/errdetails"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
35
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
35
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
@ -19,6 +19,8 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
@ -28,13 +30,13 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/syscall"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
@ -121,7 +123,7 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
|
||||
if fn != nil {
|
||||
return fn(ctx, addr)
|
||||
}
|
||||
return dialContext(ctx, "tcp", addr)
|
||||
return (&net.Dialer{}).DialContext(ctx, "tcp", addr)
|
||||
}
|
||||
|
||||
func isTemporary(err error) bool {
|
||||
@ -165,6 +167,21 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne
|
||||
conn.Close()
|
||||
}
|
||||
}(conn)
|
||||
kp := opts.KeepaliveParams
|
||||
// Validate keepalive parameters.
|
||||
if kp.Time == 0 {
|
||||
kp.Time = defaultClientKeepaliveTime
|
||||
}
|
||||
if kp.Timeout == 0 {
|
||||
kp.Timeout = defaultClientKeepaliveTimeout
|
||||
}
|
||||
keepaliveEnabled := false
|
||||
if kp.Time != infinity {
|
||||
if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
|
||||
return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
|
||||
}
|
||||
keepaliveEnabled = true
|
||||
}
|
||||
var (
|
||||
isSecure bool
|
||||
authInfo credentials.AuthInfo
|
||||
@ -188,14 +205,6 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne
|
||||
}
|
||||
isSecure = true
|
||||
}
|
||||
kp := opts.KeepaliveParams
|
||||
// Validate keepalive parameters.
|
||||
if kp.Time == 0 {
|
||||
kp.Time = defaultClientKeepaliveTime
|
||||
}
|
||||
if kp.Timeout == 0 {
|
||||
kp.Timeout = defaultClientKeepaliveTimeout
|
||||
}
|
||||
dynamicWindow := true
|
||||
icwz := int32(initialWindowSize)
|
||||
if opts.InitialConnWindowSize >= defaultWindowSize {
|
||||
@ -239,6 +248,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne
|
||||
czData: new(channelzData),
|
||||
onGoAway: onGoAway,
|
||||
onClose: onClose,
|
||||
keepaliveEnabled: keepaliveEnabled,
|
||||
}
|
||||
t.controlBuf = newControlBuffer(t.ctxDone)
|
||||
if opts.InitialWindowSize >= defaultWindowSize {
|
||||
@ -265,10 +275,9 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne
|
||||
t.statsHandler.HandleConn(t.ctx, connBegin)
|
||||
}
|
||||
if channelz.IsOn() {
|
||||
t.channelzID = channelz.RegisterNormalSocket(t, opts.ChannelzParentID, "")
|
||||
t.channelzID = channelz.RegisterNormalSocket(t, opts.ChannelzParentID, fmt.Sprintf("%s -> %s", t.localAddr, t.remoteAddr))
|
||||
}
|
||||
if t.kp.Time != infinity {
|
||||
t.keepaliveEnabled = true
|
||||
if t.keepaliveEnabled {
|
||||
go t.keepalive()
|
||||
}
|
||||
// Start the reader goroutine for incoming message. Each transport has
|
||||
|
4
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
4
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
@ -20,6 +20,7 @@ package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -31,7 +32,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
|
||||
@ -237,7 +237,7 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err
|
||||
t.stats.HandleConn(t.ctx, connBegin)
|
||||
}
|
||||
if channelz.IsOn() {
|
||||
t.channelzID = channelz.RegisterNormalSocket(t, config.ChannelzParentID, "")
|
||||
t.channelzID = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr))
|
||||
}
|
||||
t.framer.writer.Flush()
|
||||
|
||||
|
36
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
36
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
@ -22,6 +22,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -29,7 +30,6 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
@ -186,8 +186,12 @@ type Stream struct {
|
||||
headerDone uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times.
|
||||
|
||||
// hdrMu protects header and trailer metadata on the server-side.
|
||||
hdrMu sync.Mutex
|
||||
header metadata.MD // the received header metadata.
|
||||
hdrMu sync.Mutex
|
||||
// On client side, header keeps the received header metadata.
|
||||
//
|
||||
// On server side, header keeps the header set by SetHeader(). The complete
|
||||
// header will merged into this after t.WriteHeader() is called.
|
||||
header metadata.MD
|
||||
trailer metadata.MD // the key-value map of trailer metadata.
|
||||
|
||||
noHeaders bool // set if the client never received headers (set only after the stream is done).
|
||||
@ -266,10 +270,19 @@ func (s *Stream) Done() <-chan struct{} {
|
||||
return s.done
|
||||
}
|
||||
|
||||
// Header acquires the key-value pairs of header metadata once it
|
||||
// is available. It blocks until i) the metadata is ready or ii) there is no
|
||||
// header metadata or iii) the stream is canceled/expired.
|
||||
// Header returns the header metadata of the stream.
|
||||
//
|
||||
// On client side, it acquires the key-value pairs of header metadata once it is
|
||||
// available. It blocks until i) the metadata is ready or ii) there is no header
|
||||
// metadata or iii) the stream is canceled/expired.
|
||||
//
|
||||
// On server side, it returns the out header after t.WriteHeader is called.
|
||||
func (s *Stream) Header() (metadata.MD, error) {
|
||||
if s.headerChan == nil && s.header != nil {
|
||||
// On server side, return the header in stream. It will be the out
|
||||
// header after t.WriteHeader is called.
|
||||
return s.header.Copy(), nil
|
||||
}
|
||||
err := s.waitOnHeader()
|
||||
// Even if the stream is closed, header is returned if available.
|
||||
select {
|
||||
@ -710,3 +723,14 @@ type channelzData struct {
|
||||
lastMsgSentTime int64
|
||||
lastMsgRecvTime int64
|
||||
}
|
||||
|
||||
// ContextErr converts the error from context package into a status error.
|
||||
func ContextErr(err error) error {
|
||||
switch err {
|
||||
case context.DeadlineExceeded:
|
||||
return status.Error(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled:
|
||||
return status.Error(codes.Canceled, err.Error())
|
||||
}
|
||||
return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
|
||||
}
|
||||
|
66
vendor/google.golang.org/grpc/internal/transport/transport_test.go
generated
vendored
66
vendor/google.golang.org/grpc/internal/transport/transport_test.go
generated
vendored
@ -21,6 +21,7 @@ package transport
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -36,11 +37,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/internal/leakcheck"
|
||||
"google.golang.org/grpc/internal/syscall"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@ -2027,13 +2028,10 @@ func setUpHTTPStatusTest(t *testing.T, httpStatus int, wh writeHeaders) (*Stream
|
||||
wh: wh,
|
||||
}
|
||||
server.start(t, lis)
|
||||
// TODO(deklerk): we can `defer cancel()` here after we drop Go 1.6 support. Until then,
|
||||
// doing a `defer cancel()` could cause the dialer to become broken:
|
||||
// https://github.com/golang/go/issues/15078, https://github.com/golang/go/issues/15035
|
||||
connectCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second))
|
||||
defer cancel()
|
||||
client, err := newHTTP2Client(connectCtx, context.Background(), TargetInfo{Addr: lis.Addr().String()}, ConnectOptions{}, func() {}, func(GoAwayReason) {}, func() {})
|
||||
if err != nil {
|
||||
cancel() // Do not cancel in success path.
|
||||
lis.Close()
|
||||
t.Fatalf("Error creating client. Err: %v", err)
|
||||
}
|
||||
@ -2317,3 +2315,61 @@ func TestHeaderTblSize(t *testing.T) {
|
||||
t.Fatalf("expected len(limits) = 2 within 10s, got != 2")
|
||||
}
|
||||
}
|
||||
|
||||
// TestTCPUserTimeout tests that the TCP_USER_TIMEOUT socket option is set to the
|
||||
// keepalive timeout, as detailed in proposal A18
|
||||
func TestTCPUserTimeout(t *testing.T) {
|
||||
tests := []struct {
|
||||
time time.Duration
|
||||
timeout time.Duration
|
||||
}{
|
||||
{
|
||||
10 * time.Second,
|
||||
10 * time.Second,
|
||||
},
|
||||
{
|
||||
0,
|
||||
0,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
server, client, cancel := setUpWithOptions(
|
||||
t,
|
||||
0,
|
||||
&ServerConfig{
|
||||
KeepaliveParams: keepalive.ServerParameters{
|
||||
Time: tt.timeout,
|
||||
Timeout: tt.timeout,
|
||||
},
|
||||
},
|
||||
normal,
|
||||
ConnectOptions{
|
||||
KeepaliveParams: keepalive.ClientParameters{
|
||||
Time: tt.time,
|
||||
Timeout: tt.timeout,
|
||||
},
|
||||
},
|
||||
)
|
||||
defer cancel()
|
||||
defer server.stop()
|
||||
defer client.Close()
|
||||
|
||||
stream, err := client.NewStream(context.Background(), &CallHdr{})
|
||||
if err != nil {
|
||||
t.Fatalf("Client failed to create RPC request: %v", err)
|
||||
}
|
||||
client.closeStream(stream, io.EOF, true, http2.ErrCodeCancel, nil, nil, false)
|
||||
|
||||
opt, err := syscall.GetTCPUserTimeout(client.conn)
|
||||
if err != nil {
|
||||
t.Fatalf("GetTCPUserTimeout error: %v", err)
|
||||
}
|
||||
if opt < 0 {
|
||||
t.Skipf("skipping test on unsupported environment")
|
||||
}
|
||||
if timeoutMS := int(tt.timeout / time.Millisecond); timeoutMS != opt {
|
||||
t.Fatalf("wrong TCP_USER_TIMEOUT set on conn. expected %d. got %d",
|
||||
timeoutMS, opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user