diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java index 4764a6a1387..0464cb46efd 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java @@ -739,9 +739,13 @@ public void close() { } } if (sslSocketFactory != null) { + sock.setSoTimeout(proxySocketTimeout); SSLSocket sslSocket = OkHttpTlsUpgrader.upgrade( sslSocketFactory, hostnameVerifier, sock, getOverridenHost(), getOverridenPort(), connectionSpec); + // As the socket will be used for RPCs from here on, we want the socket + // timeout back to zero. + sock.setSoTimeout(0); sslSession = sslSocket.getSession(); sock = sslSocket; } @@ -761,6 +765,7 @@ sslSocketFactory, hostnameVerifier, sock, getOverridenHost(), getOverridenPort() startGoAway(0, ErrorCode.INTERNAL_ERROR, e.getStatus()); return; } catch (Exception e) { + GrpcUtil.closeQuietly(sock); onException(e); return; } finally { diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java index 0b571530db4..ec459332156 100644 --- a/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java +++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java @@ -49,6 +49,7 @@ import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import com.google.common.base.Supplier; +import com.google.common.base.Throwables; import com.google.common.base.Ticker; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; @@ -101,6 +102,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; +import java.net.SocketTimeoutException; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -2048,6 +2050,35 @@ public void proxy_serverHangs() throws Exception { sock.close(); } + @Test + public void tls_serverHangs() throws Exception { + ServerSocket serverSocket = new ServerSocket(0); + clientTransport = + new OkHttpClientTransport( + channelBuilder.useTransportSecurity().buildTransportFactory(), + new InetSocketAddress("localhost", serverSocket.getLocalPort()), + "authority", + "userAgent", + EAG_ATTRS, + NO_PROXY, + tooManyPingsRunnable, + null); + clientTransport.proxySocketTimeout = 10; + clientTransport.start(transportListener); + + Socket sock = serverSocket.accept(); + serverSocket.close(); + + ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(Status.class); + verify(transportListener, timeout(200)) + .transportShutdown(statusCaptor.capture(), any(DisconnectError.class)); + verify(transportListener, timeout(TIME_OUT_MS)).transportTerminated(); + assertThat(statusCaptor.getValue().getCode()).isEqualTo(Status.Code.UNAVAILABLE); + assertThat(Throwables.getRootCause(statusCaptor.getValue().getCause())) + .isInstanceOf(SocketTimeoutException.class); + sock.close(); + } + @Test public void goAway_notUtf8() throws Exception { initTransport();