mirror of https://github.com/grpc/grpc-go.git
This commit is contained in:
parent
1634254ac6
commit
e8599844e7
|
|
@ -238,7 +238,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
||||||
kp.Timeout = defaultServerKeepaliveTimeout
|
kp.Timeout = defaultServerKeepaliveTimeout
|
||||||
}
|
}
|
||||||
if kp.Time != infinity {
|
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)
|
return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,18 +24,23 @@ package transport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
"google.golang.org/grpc/credentials"
|
||||||
"google.golang.org/grpc/internal/channelz"
|
"google.golang.org/grpc/internal/channelz"
|
||||||
"google.golang.org/grpc/internal/grpctest"
|
"google.golang.org/grpc/internal/grpctest"
|
||||||
"google.golang.org/grpc/internal/syscall"
|
"google.golang.org/grpc/internal/syscall"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
|
"google.golang.org/grpc/testdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultTestTimeout = 10 * time.Second
|
const defaultTestTimeout = 10 * time.Second
|
||||||
|
|
@ -581,24 +586,49 @@ func (s) TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient(t *testing.T
|
||||||
// the keepalive timeout, as detailed in proposal A18.
|
// the keepalive timeout, as detailed in proposal A18.
|
||||||
func (s) TestTCPUserTimeout(t *testing.T) {
|
func (s) TestTCPUserTimeout(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
tls bool
|
||||||
time time.Duration
|
time time.Duration
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
clientWantTimeout time.Duration
|
clientWantTimeout time.Duration
|
||||||
serverWantTimeout time.Duration
|
serverWantTimeout time.Duration
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
false,
|
||||||
10 * time.Second,
|
10 * time.Second,
|
||||||
10 * time.Second,
|
10 * time.Second,
|
||||||
10 * 1000 * time.Millisecond,
|
10 * 1000 * time.Millisecond,
|
||||||
10 * 1000 * time.Millisecond,
|
10 * 1000 * time.Millisecond,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
false,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
20 * 1000 * time.Millisecond,
|
20 * 1000 * time.Millisecond,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
false,
|
||||||
|
infinity,
|
||||||
|
infinity,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
10 * time.Second,
|
||||||
|
10 * time.Second,
|
||||||
|
10 * 1000 * time.Millisecond,
|
||||||
|
10 * 1000 * time.Millisecond,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
20 * 1000 * time.Millisecond,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
infinity,
|
infinity,
|
||||||
infinity,
|
infinity,
|
||||||
0,
|
0,
|
||||||
|
|
@ -606,22 +636,32 @@ func (s) TestTCPUserTimeout(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
server, client, cancel := setUpWithOptions(
|
sopts := &ServerConfig{
|
||||||
t,
|
|
||||||
0,
|
|
||||||
&ServerConfig{
|
|
||||||
KeepaliveParams: keepalive.ServerParameters{
|
KeepaliveParams: keepalive.ServerParameters{
|
||||||
Time: tt.time,
|
Time: tt.time,
|
||||||
Timeout: tt.timeout,
|
Timeout: tt.timeout,
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
normal,
|
|
||||||
ConnectOptions{
|
copts := ConnectOptions{
|
||||||
KeepaliveParams: keepalive.ClientParameters{
|
KeepaliveParams: keepalive.ClientParameters{
|
||||||
Time: tt.time,
|
Time: tt.time,
|
||||||
Timeout: tt.timeout,
|
Timeout: tt.timeout,
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
|
|
||||||
|
if tt.tls {
|
||||||
|
copts.TransportCredentials = makeTLSCreds(t, "x509/client1_cert.pem", "x509/client1_key.pem", "x509/server_ca_cert.pem")
|
||||||
|
sopts.Credentials = makeTLSCreds(t, "x509/server1_cert.pem", "x509/server1_key.pem", "x509/client_ca_cert.pem")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
server, client, cancel := setUpWithOptions(
|
||||||
|
t,
|
||||||
|
0,
|
||||||
|
sopts,
|
||||||
|
normal,
|
||||||
|
copts,
|
||||||
)
|
)
|
||||||
defer func() {
|
defer func() {
|
||||||
client.Close(fmt.Errorf("closed manually by test"))
|
client.Close(fmt.Errorf("closed manually by test"))
|
||||||
|
|
@ -630,6 +670,7 @@ func (s) TestTCPUserTimeout(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var sc *http2Server
|
var sc *http2Server
|
||||||
|
var srawConn net.Conn
|
||||||
// Wait until the server transport is setup.
|
// Wait until the server transport is setup.
|
||||||
for {
|
for {
|
||||||
server.mu.Lock()
|
server.mu.Lock()
|
||||||
|
|
@ -644,6 +685,7 @@ func (s) TestTCPUserTimeout(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("Failed to convert %v to *http2Server", k)
|
t.Fatalf("Failed to convert %v to *http2Server", k)
|
||||||
}
|
}
|
||||||
|
srawConn = server.conns[k]
|
||||||
}
|
}
|
||||||
server.mu.Unlock()
|
server.mu.Unlock()
|
||||||
break
|
break
|
||||||
|
|
@ -657,6 +699,9 @@ func (s) TestTCPUserTimeout(t *testing.T) {
|
||||||
}
|
}
|
||||||
client.CloseStream(stream, io.EOF)
|
client.CloseStream(stream, io.EOF)
|
||||||
|
|
||||||
|
// check client TCP user timeout only when non TLS
|
||||||
|
// TODO : find a way to get the underlying conn for client when TLS
|
||||||
|
if !tt.tls {
|
||||||
cltOpt, err := syscall.GetTCPUserTimeout(client.conn)
|
cltOpt, err := syscall.GetTCPUserTimeout(client.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
|
t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
|
||||||
|
|
@ -667,17 +712,49 @@ func (s) TestTCPUserTimeout(t *testing.T) {
|
||||||
if gotTimeout := time.Duration(cltOpt) * time.Millisecond; gotTimeout != tt.clientWantTimeout {
|
if gotTimeout := time.Duration(cltOpt) * time.Millisecond; gotTimeout != tt.clientWantTimeout {
|
||||||
t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.clientWantTimeout)
|
t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.clientWantTimeout)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
srvOpt, err := syscall.GetTCPUserTimeout(sc.conn)
|
scConn := sc.conn
|
||||||
|
if tt.tls {
|
||||||
|
if _, ok := sc.conn.(*net.TCPConn); ok {
|
||||||
|
t.Fatalf("sc.conn is should have wrapped conn with TLS")
|
||||||
|
}
|
||||||
|
scConn = srawConn
|
||||||
|
}
|
||||||
|
// verify the type of scConn (on which TCP user timeout will be got)
|
||||||
|
if _, ok := scConn.(*net.TCPConn); !ok {
|
||||||
|
t.Fatalf("server underlying conn is of type %T, want net.TCPConn", scConn)
|
||||||
|
}
|
||||||
|
srvOpt, err := syscall.GetTCPUserTimeout(scConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
|
t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
|
||||||
}
|
}
|
||||||
if gotTimeout := time.Duration(srvOpt) * time.Millisecond; gotTimeout != tt.serverWantTimeout {
|
if gotTimeout := time.Duration(srvOpt) * time.Millisecond; gotTimeout != tt.serverWantTimeout {
|
||||||
t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.serverWantTimeout)
|
t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.serverWantTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeTLSCreds(t *testing.T, certPath, keyPath, rootsPath string) credentials.TransportCredentials {
|
||||||
|
cert, err := tls.LoadX509KeyPair(testdata.Path(certPath), testdata.Path(keyPath))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("tls.LoadX509KeyPair(%q, %q) failed: %v", certPath, keyPath, err)
|
||||||
|
}
|
||||||
|
b, err := os.ReadFile(testdata.Path(rootsPath))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("os.ReadFile(%q) failed: %v", rootsPath, err)
|
||||||
|
}
|
||||||
|
roots := x509.NewCertPool()
|
||||||
|
if !roots.AppendCertsFromPEM(b) {
|
||||||
|
t.Fatal("failed to append certificates")
|
||||||
|
}
|
||||||
|
return credentials.NewTLS(&tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: roots,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// checkForHealthyStream attempts to create a stream and return error if any.
|
// checkForHealthyStream attempts to create a stream and return error if any.
|
||||||
// The stream created is closed right after to avoid any leakages.
|
// The stream created is closed right after to avoid any leakages.
|
||||||
func checkForHealthyStream(client *http2Client) error {
|
func checkForHealthyStream(client *http2Client) error {
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ type server struct {
|
||||||
port string
|
port string
|
||||||
startedErr chan error // error (or nil) with server start value
|
startedErr chan error // error (or nil) with server start value
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
conns map[ServerTransport]bool
|
conns map[ServerTransport]net.Conn
|
||||||
h *testStreamHandler
|
h *testStreamHandler
|
||||||
ready chan struct{}
|
ready chan struct{}
|
||||||
channelzID *channelz.Identifier
|
channelzID *channelz.Identifier
|
||||||
|
|
@ -329,13 +329,14 @@ func (s *server) start(t *testing.T, port int, serverConfig *ServerConfig, ht hT
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.port = p
|
s.port = p
|
||||||
s.conns = make(map[ServerTransport]bool)
|
s.conns = make(map[ServerTransport]net.Conn)
|
||||||
s.startedErr <- nil
|
s.startedErr <- nil
|
||||||
for {
|
for {
|
||||||
conn, err := s.lis.Accept()
|
conn, err := s.lis.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
rawConn := conn
|
||||||
transport, err := NewServerTransport(conn, serverConfig)
|
transport, err := NewServerTransport(conn, serverConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
@ -346,7 +347,7 @@ func (s *server) start(t *testing.T, port int, serverConfig *ServerConfig, ht hT
|
||||||
transport.Close(errors.New("s.conns is nil"))
|
transport.Close(errors.New("s.conns is nil"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.conns[transport] = true
|
s.conns[transport] = rawConn
|
||||||
h := &testStreamHandler{t: transport.(*http2Server)}
|
h := &testStreamHandler{t: transport.(*http2Server)}
|
||||||
s.h = h
|
s.h = h
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue