diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:17:05 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:17:05 +0000 |
commit | b0530302a266f69bb70ec76600c106eea24bbece (patch) | |
tree | 1cab24f5c6213e40794b612fa7017cf8ea745fb6 | |
parent | 04873d89aa01afa393e6f28e06b3763361b9548c (diff) | |
parent | 527304d57c92232e7c6f9b0ceb962f909d9df8b6 (diff) | |
download | okhttp-b0530302a266f69bb70ec76600c106eea24bbece.tar.gz |
Snap for 10447354 from 527304d57c92232e7c6f9b0ceb962f909d9df8b6 to mainline-networking-releaseaml_net_341311010aml_net_341310020aml_net_341014000aml_net_340913000
Change-Id: Ib7414ac5fd3322d6d25c9cd4a52e64f963269b68
14 files changed, 245 insertions, 53 deletions
@@ -32,6 +32,16 @@ license { ], } +java_defaults { + name: "okhttp_errorprone_defaults", + errorprone: { + javacflags: [ + "-Xep:InvalidTimeZoneID:WARN", + "-Xep:TryFailThrowable:WARN", + ], + }, +} + // The source files that contribute to Android's core library APIs. filegroup { name: "okhttp_api_files", @@ -49,6 +59,7 @@ nojarjar_visibility = [ // non-jarjar'd version of okhttp to compile the tests against java_library { name: "okhttp-nojarjar", + defaults: ["okhttp_errorprone_defaults"], visibility: nojarjar_visibility, srcs: [ "android/src/main/java/**/*.java", @@ -91,6 +102,7 @@ filegroup { java_library { name: "okhttp", + defaults: ["okhttp_errorprone_defaults"], visibility: [ "//art/build/apex", "//art/build/sdk", @@ -141,9 +153,11 @@ java_library { // third-party or unbundled applications or libraries that require OkHttp. java_library { name: "okhttp-norepackage", + defaults: ["okhttp_errorprone_defaults"], host_supported: true, apex_available: [ "com.android.adservices", + "com.android.devicelock", "com.android.extservices", "com.android.ondevicepersonalization", ], @@ -172,6 +186,9 @@ java_library { sdk_version: "core_current", // Make sure that this will be added to the sdk snapshot for S. min_sdk_version: "30", + // This jar is packaged as part of the ART module host exports, use -target 8 so that it works + // with old JDKs. + java_version: "1.8", } // Generate Version.java based on the version number from pom.xml. @@ -200,6 +217,7 @@ java_library { java_library { name: "okhttp-tests-nojarjar", + defaults: ["okhttp_errorprone_defaults"], visibility: nojarjar_visibility, srcs: [ "android/test/java/**/*.java", diff --git a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockResponse.java b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockResponse.java index db68595..c46d96d 100644 --- a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockResponse.java +++ b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockResponse.java @@ -21,6 +21,7 @@ import com.squareup.okhttp.internal.framed.Settings; import com.squareup.okhttp.ws.WebSocketListener; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; import java.util.concurrent.TimeUnit; import okio.Buffer; @@ -38,6 +39,7 @@ public final class MockResponse implements Cloneable { private TimeUnit throttlePeriodUnit = TimeUnit.SECONDS; private SocketPolicy socketPolicy = SocketPolicy.KEEP_OPEN; + private Consumer<SocketPolicy> socketShutdownListener = null; private long bodyDelayAmount = 0; private TimeUnit bodyDelayUnit = TimeUnit.MILLISECONDS; @@ -195,6 +197,28 @@ public final class MockResponse implements Cloneable { } /** + * Sets a listener that can wait until a socket is closed. This is important if the + * {@link SocketPolicy} gets set to something that shuts down the socket after a transaction and + * that socket may get reused in subsequent calls if they happen too fast. + * + * @param listener The listener that will be notified when a socket is closed. This could be an + * instance of {@link SocketShutdownListener}. + * + * @see SocketPolicy + * @see SocketShutdownListener + */ + public MockResponse setSocketShutdownListener(Consumer<SocketPolicy> listener) { + this.socketShutdownListener = listener; + return this; + } + + void notifyShutdown(SocketPolicy reason) { + if (socketShutdownListener != null) { + socketShutdownListener.accept(reason); + } + } + + /** * Throttles the response body writer to sleep for the given period after each * series of {@code bytesPerPeriod} bytes are written. Use this to simulate * network behavior. diff --git a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java index b15e92f..7a3deee 100644 --- a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java +++ b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/MockWebServer.java @@ -554,11 +554,14 @@ public final class MockWebServer implements TestRule { // See warnings associated with these socket policies in SocketPolicy. if (response.getSocketPolicy() == SocketPolicy.DISCONNECT_AT_END) { socket.close(); + response.notifyShutdown(SocketPolicy.DISCONNECT_AT_END); return false; } else if (response.getSocketPolicy() == SocketPolicy.SHUTDOWN_INPUT_AT_END) { socket.shutdownInput(); + response.notifyShutdown(SocketPolicy.SHUTDOWN_INPUT_AT_END); } else if (response.getSocketPolicy() == SocketPolicy.SHUTDOWN_OUTPUT_AT_END) { socket.shutdownOutput(); + response.notifyShutdown(SocketPolicy.SHUTDOWN_OUTPUT_AT_END); } sequenceNumber++; diff --git a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketPolicy.java b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketPolicy.java index cdbbf72..6f4602f 100644 --- a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketPolicy.java +++ b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketPolicy.java @@ -26,8 +26,9 @@ package com.squareup.okhttp.mockwebserver; * server may not have had time to close the socket. The socket will be closed at an indeterminate * point before or during the second request. It may be closed after client has started sending the * request body. If a request body is not retryable then the client may fail the request, making - * client behavior non-deterministic. Add delays in the client to improve the chances that the - * server has closed the socket before follow up requests are made. + * client behavior non-deterministic. In order to prevent that {@link + * MockResponse#setSocketShutdownListener} can be used. Otherwise, add delays in the client to + * improve the chances that the server has closed the socket before follow up requests are made. */ public enum SocketPolicy { diff --git a/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketShutdownListener.java b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketShutdownListener.java new file mode 100644 index 0000000..b83ce4a --- /dev/null +++ b/mockwebserver/src/main/java/com/squareup/okhttp/mockwebserver/SocketShutdownListener.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Google Inc. + * + * 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 com.squareup.okhttp.mockwebserver; + +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; + +/** + * Utility class for registering as a listener to {@link MockResponse#setSocketShutdownListener}. + * + * An instance will wait for a single shutdown callback. Once triggered, the listener will stay in a + * "shutdown occurred" state. + * + * @see SocketPolicy + */ +public class SocketShutdownListener implements Consumer<SocketPolicy> { + + final CountDownLatch shutdownLatch = new CountDownLatch(1); + + @Override + public void accept(SocketPolicy reason) { + shutdownLatch.countDown(); + } + + public void waitForSocketShutdown() { + try { + shutdownLatch.await(); + } catch (InterruptedException e) { + } + } +} diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java index 0b18783..605ca68 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/CallTest.java @@ -90,6 +90,20 @@ public final class CallTest { @Rule public final MockWebServer server2 = new MockWebServer(); @Rule public final InMemoryFileSystem fileSystem = new InMemoryFileSystem(); + // Android-added: Use TLS 1.3 and 1.2 for testing + private static final ConnectionSpec TLS_SPEC_1_3 = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_3) + .build(); + + private static final ConnectionSpec TLS_SPEC_1_2 = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build(); + + private static final List<ConnectionSpec> TLS_SPEC_NO_V1 + = Arrays.asList(TLS_SPEC_1_3, TLS_SPEC_1_2); + private SSLContext sslContext = SslContextBuilder.localhost(); private OkHttpClient client = new OkHttpClient(); private RecordingCallback callback = new RecordingCallback(); @@ -915,6 +929,8 @@ public final class CallTest { server.enqueue(new MockResponse().setBody("abc")); suppressTlsFallbackScsv(client); + // Android-added: Use TLS 1.3 and 1.2 for testing + client.setConnectionSpecs(TLS_SPEC_NO_V1); client.setHostnameVerifier(new RecordingHostnameVerifier()); client.setDns(new SingleInetAddressDns()); @@ -933,12 +949,18 @@ public final class CallTest { server.useHttps(sslContext.getSocketFactory(), false); server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); + // Android-added: Need an extra handshake fail when using TLS 1.3 and 1.2 for testing. + // Seems to be a testing quirk due to adding two ConnectionSpecs and has no impact + // on the logic being tested or the expected outcomes, so not gonna dig too deep. + server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); RecordingSSLSocketFactory clientSocketFactory = new RecordingSSLSocketFactory(sslContext.getSocketFactory()); client.setSslSocketFactory(clientSocketFactory); client.setHostnameVerifier(new RecordingHostnameVerifier()); client.setDns(new SingleInetAddressDns()); + // Android-added: Use TLS 1.3 and 1.2 for testing + client.setConnectionSpecs(TLS_SPEC_NO_V1); Request request = new Request.Builder().url(server.url("/")).build(); try { @@ -961,6 +983,8 @@ public final class CallTest { suppressTlsFallbackScsv(client); client.setHostnameVerifier(new RecordingHostnameVerifier()); + // Android-added: Use TLS 1.3 and 1.2 for testing + client.setConnectionSpecs(TLS_SPEC_NO_V1); Request request = new Request.Builder() .url(server.url("/")) diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionReuseTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionReuseTest.java index f445dac..93219bf 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionReuseTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionReuseTest.java @@ -19,6 +19,7 @@ import com.squareup.okhttp.internal.SslContextBuilder; import com.squareup.okhttp.mockwebserver.MockResponse; import com.squareup.okhttp.mockwebserver.MockWebServer; import com.squareup.okhttp.mockwebserver.SocketPolicy; +import com.squareup.okhttp.mockwebserver.SocketShutdownListener; import com.squareup.okhttp.testing.RecordingHostnameVerifier; import java.util.Arrays; import java.util.concurrent.TimeUnit; @@ -166,8 +167,10 @@ public final class ConnectionReuseTest { } @Test public void staleConnectionNotReusedForNonIdempotentRequest() throws Exception { + SocketShutdownListener shutdownListener = new SocketShutdownListener(); server.enqueue(new MockResponse().setBody("a") - .setSocketPolicy(SocketPolicy.SHUTDOWN_OUTPUT_AT_END)); + .setSocketPolicy(SocketPolicy.SHUTDOWN_OUTPUT_AT_END) + .setSocketShutdownListener(shutdownListener)); server.enqueue(new MockResponse().setBody("b")); Request requestA = new Request.Builder() @@ -177,6 +180,8 @@ public final class ConnectionReuseTest { assertEquals("a", responseA.body().string()); assertEquals(0, server.takeRequest().getSequenceNumber()); + shutdownListener.waitForSocketShutdown(); + Request requestB = new Request.Builder() .url(server.url("/")) .post(RequestBody.create(MediaType.parse("text/plain"), "b")) diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionSpecTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionSpecTest.java index 2318a68..adb6160 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionSpecTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/ConnectionSpecTest.java @@ -21,6 +21,7 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; +import org.junit.Assume; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -80,65 +81,75 @@ public final class ConnectionSpecTest { @Test public void tls_defaultCiphers_noFallbackIndicator() throws Exception { ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true) - .tlsVersions(TlsVersion.TLS_1_2) + // Android-changed: Use TLS 1.3 and 1.2 for testing + .tlsVersions(TlsVersion.TLS_1_3) .supportsTlsExtensions(false) .build(); SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); socket.setEnabledCipherSuites(new String[] { CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName, - // Android-changed: Replace removed CBC cipher with GCM version - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256.javaName, + // Android-changed: USe TLS 1.3 and 1.2 for testing - TLS 1.3 suites are implicit + // CipherSuite.TLS_AES_128_GCM_SHA384.javaName, }); socket.setEnabledProtocols(new String[] { + // Android-changed: Use TLS 1.3 and 1.2 for testing + TlsVersion.TLS_1_3.javaName, TlsVersion.TLS_1_2.javaName, - TlsVersion.TLS_1_1.javaName, }); assertTrue(tlsSpec.isCompatible(socket)); tlsSpec.apply(socket, false /* isFallback */); - assertEquals(set(TlsVersion.TLS_1_2.javaName), set(socket.getEnabledProtocols())); + // Android-changed: Use TLS 1.3 and 1.2 for testing + assertEquals(set(TlsVersion.TLS_1_3.javaName), set(socket.getEnabledProtocols())); Set<String> expectedCipherSet = set( CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName, - // Android-changed: Replace removed CBC cipher with GCM version - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256.javaName); - assertEquals(expectedCipherSet, expectedCipherSet); + // Android-changed: USe TLS 1.3 and 1.2 for testing - TLS 1.3 suites are implicit + CipherSuite.TLS_AES_128_GCM_SHA256.javaName, + CipherSuite.TLS_AES_256_GCM_SHA384.javaName, + CipherSuite.TLS_CHACHA20_POLY1305_SHA256.javaName); + assertEquals(expectedCipherSet, set(socket.getEnabledCipherSuites())); } @Test public void tls_defaultCiphers_withFallbackIndicator() throws Exception { ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true) - .tlsVersions(TlsVersion.TLS_1_2) + // Android-changed: Use TLS 1.3 and 1.2 for testing + .tlsVersions(TlsVersion.TLS_1_3) .supportsTlsExtensions(false) .build(); SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); socket.setEnabledCipherSuites(new String[] { CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName, - // Android-changed: Replace removed CBC cipher with GCM version - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256.javaName, + // Android-changed: USe TLS 1.3 and 1.2 for testing - TLS 1.3 suites are implicit + // CipherSuite.TLS_AES_128_GCM_SHA384.javaName, }); socket.setEnabledProtocols(new String[] { + // Android-changed: Use TLS 1.3 and 1.2 for testing + TlsVersion.TLS_1_3.javaName, TlsVersion.TLS_1_2.javaName, - TlsVersion.TLS_1_1.javaName, }); assertTrue(tlsSpec.isCompatible(socket)); tlsSpec.apply(socket, true /* isFallback */); - assertEquals(set(TlsVersion.TLS_1_2.javaName), set(socket.getEnabledProtocols())); + // Android-changed: Use TLS 1.3 and 1.2 for testing + assertEquals(set(TlsVersion.TLS_1_3.javaName), set(socket.getEnabledProtocols())); Set<String> expectedCipherSet = set( CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName, - // Android-changed: Replace removed CBC cipher with GCM version - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256.javaName); + // Android-changed: USe TLS 1.3 and 1.2 for testing - TLS 1.3 suites are implicit + CipherSuite.TLS_AES_128_GCM_SHA256.javaName, + CipherSuite.TLS_AES_256_GCM_SHA384.javaName, + CipherSuite.TLS_CHACHA20_POLY1305_SHA256.javaName); if (Arrays.asList(socket.getSupportedCipherSuites()).contains("TLS_FALLBACK_SCSV")) { expectedCipherSet.add("TLS_FALLBACK_SCSV"); } - assertEquals(expectedCipherSet, expectedCipherSet); + assertEquals(expectedCipherSet, set(socket.getEnabledCipherSuites())); } @Test public void tls_explicitCiphers() throws Exception { @@ -151,12 +162,13 @@ public final class ConnectionSpecTest { SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); socket.setEnabledCipherSuites(new String[] { CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName, - // Android-changed: Replace removed CBC cipher with GCM version - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256.javaName, + // Android-changed: USe TLS 1.3 and 1.2 for testing - TLS 1.3 suites are implicit + // CipherSuite.TLS_AES_128_GCM_SHA384.javaName, }); socket.setEnabledProtocols(new String[] { + // Android-changed: Use TLS 1.3 and 1.2 for testing + TlsVersion.TLS_1_3.javaName, TlsVersion.TLS_1_2.javaName, - TlsVersion.TLS_1_1.javaName, }); assertTrue(tlsSpec.isCompatible(socket)); @@ -189,8 +201,9 @@ public final class ConnectionSpecTest { SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); socket.setEnabledProtocols(new String[] { + // Android-changed: Use TLS 1.3 and 1.2 for testing + TlsVersion.TLS_1_3.javaName, TlsVersion.TLS_1_2.javaName, - TlsVersion.TLS_1_1.javaName, }); socket.setEnabledCipherSuites(new String[] { @@ -236,12 +249,14 @@ public final class ConnectionSpecTest { SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); sslSocket.setEnabledProtocols(new String[] { - TlsVersion.TLS_1_0.javaName(), - TlsVersion.TLS_1_1.javaName() + // Android-changed: Use TLS 1.3 and 1.2 for testing + TlsVersion.TLS_1_2.javaName, + TlsVersion.TLS_1_3.javaName, }); tlsSpec.apply(sslSocket, false); - assertEquals(Arrays.asList(TlsVersion.TLS_1_0.javaName(), TlsVersion.TLS_1_1.javaName()), + // Android-changed: Use TLS 1.3 and 1.2 for testing + assertEquals(Arrays.asList(TlsVersion.TLS_1_2.javaName(), TlsVersion.TLS_1_3.javaName()), Arrays.asList(sslSocket.getEnabledProtocols())); } @@ -253,6 +268,11 @@ public final class ConnectionSpecTest { .build(); SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); + // Android-changed: Only testable if TLS v1.1 is available as TLS 1.3 ciphers are + // not changeable on Android. + Assume.assumeTrue( + Arrays.asList(socket.getEnabledProtocols()).contains(TlsVersion.TLS_1_1.javaName)); + socket.setEnabledCipherSuites(new String[] { CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName, }); diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/URLConnectionTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/URLConnectionTest.java index a3e1450..1976523 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/URLConnectionTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/URLConnectionTest.java @@ -28,6 +28,7 @@ import com.squareup.okhttp.mockwebserver.MockResponse; import com.squareup.okhttp.mockwebserver.MockWebServer; import com.squareup.okhttp.mockwebserver.RecordedRequest; import com.squareup.okhttp.mockwebserver.SocketPolicy; +import com.squareup.okhttp.mockwebserver.SocketShutdownListener; import com.squareup.okhttp.testing.RecordingHostnameVerifier; import java.io.IOException; import java.io.InputStream; @@ -105,6 +106,20 @@ public final class URLConnectionTest { @Rule public final MockWebServer server2 = new MockWebServer(); @Rule public final TemporaryFolder tempDir = new TemporaryFolder(); + // Android-added: Use TLS 1.3 and 1.2 for testing + private static final ConnectionSpec TLS_SPEC_1_3 = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_3) + .build(); + + private static final ConnectionSpec TLS_SPEC_1_2 = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build(); + + private static final List<ConnectionSpec> TLS_SPEC_NO_V1 + = Arrays.asList(TLS_SPEC_1_3, TLS_SPEC_1_2); + private SSLContext sslContext = SslContextBuilder.localhost(); private OkUrlFactory client; private HttpURLConnection connection; @@ -409,8 +424,10 @@ public final class URLConnectionTest { } private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception { + SocketShutdownListener shutdownListener = new SocketShutdownListener(); server.enqueue(new MockResponse().setBody("This connection won't pool properly") - .setSocketPolicy(socketPolicy)); + .setSocketPolicy(socketPolicy) + .setSocketShutdownListener(shutdownListener)); MockResponse responseAfter = new MockResponse().setBody("This comes after a busted connection"); server.enqueue(responseAfter); server.enqueue(responseAfter); // Enqueue 2x because the broken connection may be reused. @@ -420,9 +437,7 @@ public final class URLConnectionTest { assertContent("This connection won't pool properly", connection1); assertEquals(0, server.takeRequest().getSequenceNumber()); - // Give the server time to enact the socket policy if it's one that could happen after the - // client has received the response. - Thread.sleep(500); + shutdownListener.waitForSocketShutdown(); HttpURLConnection connection2 = client.open(server.getUrl("/b")); connection2.setReadTimeout(100); @@ -605,6 +620,7 @@ public final class URLConnectionTest { server.enqueue(new MockResponse().setBody("this response comes via SSL")); suppressTlsFallbackScsv(client.client()); + client.client().setConnectionSpecs(TLS_SPEC_NO_V1); client.client().setHostnameVerifier(new RecordingHostnameVerifier()); connection = client.open(server.getUrl("/foo")); @@ -612,7 +628,7 @@ public final class URLConnectionTest { RecordedRequest request = server.takeRequest(); assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); - assertEquals(TlsVersion.TLS_1_0, request.getTlsVersion()); + assertEquals(TlsVersion.TLS_1_2, request.getTlsVersion()); } @Test public void connectViaHttpsWithSSLFallbackFailuresRecorded() throws Exception { @@ -621,6 +637,7 @@ public final class URLConnectionTest { server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); suppressTlsFallbackScsv(client.client()); + client.client().setConnectionSpecs(TLS_SPEC_NO_V1); client.client().setDns(new SingleInetAddressDns()); client.client().setHostnameVerifier(new RecordingHostnameVerifier()); @@ -641,24 +658,26 @@ public final class URLConnectionTest { * https://github.com/square/okhttp/issues/515 */ @Test public void sslFallbackNotUsedWhenRecycledConnectionFails() throws Exception { + SocketShutdownListener shutdownListener = new SocketShutdownListener(); server.useHttps(sslContext.getSocketFactory(), false); server.enqueue(new MockResponse() .setBody("abc") - .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END)); + .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END) + .setSocketShutdownListener(shutdownListener)); server.enqueue(new MockResponse().setBody("def")); suppressTlsFallbackScsv(client.client()); + client.client().setConnectionSpecs(TLS_SPEC_NO_V1); client.client().setHostnameVerifier(new RecordingHostnameVerifier()); assertContent("abc", client.open(server.getUrl("/"))); - // Give the server time to disconnect. - Thread.sleep(500); + shutdownListener.waitForSocketShutdown(); assertContent("def", client.open(server.getUrl("/"))); Set<TlsVersion> tlsVersions = - EnumSet.of(TlsVersion.TLS_1_0, TlsVersion.TLS_1_2); // v1.2 on OpenJDK 8. + EnumSet.of(TlsVersion.TLS_1_3); RecordedRequest request1 = server.takeRequest(); assertTrue(tlsVersions.contains(request1.getTlsVersion())); @@ -1273,9 +1292,11 @@ public final class URLConnectionTest { } @Test public void transparentGzipWorksAfterExceptionRecovery() throws Exception { + SocketShutdownListener shutdownListener = new SocketShutdownListener(); server.enqueue(new MockResponse() .setBody("a") - .setSocketPolicy(SHUTDOWN_INPUT_AT_END)); + .setSocketPolicy(SHUTDOWN_INPUT_AT_END) + .setSocketShutdownListener(shutdownListener)); server.enqueue(new MockResponse() .addHeader("Content-Encoding: gzip") .setBody(gzip("b"))); @@ -1283,8 +1304,7 @@ public final class URLConnectionTest { // Seed the pool with a bad connection. assertContent("a", client.open(server.getUrl("/"))); - // Give the server time to disconnect. - Thread.sleep(500); + shutdownListener.waitForSocketShutdown(); // This connection will need to be recovered. When it is, transparent gzip should still work! assertContent("b", client.open(server.getUrl("/"))); @@ -2674,14 +2694,16 @@ public final class URLConnectionTest { private void reusedConnectionFailsWithPost(TransferKind transferKind, int requestSize) throws Exception { - server.enqueue(new MockResponse().setBody("A").setSocketPolicy(DISCONNECT_AT_END)); + SocketShutdownListener shutdownListener = new SocketShutdownListener(); + server.enqueue(new MockResponse().setBody("A") + .setSocketPolicy(DISCONNECT_AT_END) + .setSocketShutdownListener(shutdownListener)); server.enqueue(new MockResponse().setBody("B")); server.enqueue(new MockResponse().setBody("C")); assertContent("A", client.open(server.getUrl("/a"))); - // Give the server time to disconnect. - Thread.sleep(500); + shutdownListener.waitForSocketShutdown(); // If the request body is larger than OkHttp's replay buffer, the failure may still occur. byte[] requestBody = new byte[requestSize]; diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/ConnectionSpecSelectorTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/ConnectionSpecSelectorTest.java index c94cc23..b96c328 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/ConnectionSpecSelectorTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/ConnectionSpecSelectorTest.java @@ -41,11 +41,24 @@ public class ConnectionSpecSelectorTest { private SSLContext sslContext = SslContextBuilder.localhost(); + // Android-changed: Use TLS 1.3 and 1.2 for testing + private static final ConnectionSpec TLS_SPEC_1_3 = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_3) + .build(); + + private static final ConnectionSpec TLS_SPEC_1_2 = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build(); + + @Test public void nonRetryableIOException() throws Exception { ConnectionSpecSelector connectionSpecSelector = - createConnectionSpecSelector(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS); - SSLSocket socket = createSocketWithEnabledProtocols(TlsVersion.TLS_1_1, TlsVersion.TLS_1_0); + // Android-changed: Use TLS 1.3 and 1.2 for testing + createConnectionSpecSelector(TLS_SPEC_1_3, TLS_SPEC_1_2); + SSLSocket socket = createSocketWithEnabledProtocols(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2); connectionSpecSelector.configureSecureSocket(socket); boolean retry = connectionSpecSelector.connectionFailed( @@ -57,8 +70,9 @@ public class ConnectionSpecSelectorTest { @Test public void nonRetryableSSLHandshakeException() throws Exception { ConnectionSpecSelector connectionSpecSelector = - createConnectionSpecSelector(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS); - SSLSocket socket = createSocketWithEnabledProtocols(TlsVersion.TLS_1_1, TlsVersion.TLS_1_0); + // Android-changed: Use TLS 1.3 and 1.2 + createConnectionSpecSelector(TLS_SPEC_1_3, TLS_SPEC_1_2); + SSLSocket socket = createSocketWithEnabledProtocols(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2); connectionSpecSelector.configureSecureSocket(socket); SSLHandshakeException trustIssueException = @@ -72,8 +86,9 @@ public class ConnectionSpecSelectorTest { @Test public void retryableSSLHandshakeException() throws Exception { ConnectionSpecSelector connectionSpecSelector = - createConnectionSpecSelector(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS); - SSLSocket socket = createSocketWithEnabledProtocols(TlsVersion.TLS_1_1, TlsVersion.TLS_1_0); + // Android-changed: Use TLS 1.3 and 1.2 + createConnectionSpecSelector(TLS_SPEC_1_3, TLS_SPEC_1_2); + SSLSocket socket = createSocketWithEnabledProtocols(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2); connectionSpecSelector.configureSecureSocket(socket); boolean retry = connectionSpecSelector.connectionFailed(RETRYABLE_EXCEPTION); @@ -88,24 +103,28 @@ public class ConnectionSpecSelectorTest { .tlsVersions(TlsVersion.SSL_3_0) .build(); + // Android-changed: Use TLS 1.3 and 1.2 for testing ConnectionSpecSelector connectionSpecSelector = createConnectionSpecSelector( - ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, sslV3); + TLS_SPEC_1_3, TLS_SPEC_1_2, sslV3); - TlsVersion[] enabledSocketTlsVersions = { TlsVersion.TLS_1_1, TlsVersion.TLS_1_0 }; + // Android-changed: Use TLS 1.3 and 1.2 for testing + TlsVersion[] enabledSocketTlsVersions = { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }; SSLSocket socket = createSocketWithEnabledProtocols(enabledSocketTlsVersions); - // MODERN_TLS is used here. + // Android-changed: Use TLS 1.3 and 1.2 for testing + // TLS_SPEC_1_3 is used here. connectionSpecSelector.configureSecureSocket(socket); - assertEnabledProtocols(socket, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0); + assertEnabledProtocols(socket, TlsVersion.TLS_1_3); boolean retry = connectionSpecSelector.connectionFailed(RETRYABLE_EXCEPTION); assertTrue(retry); socket.close(); - // COMPATIBLE_TLS is used here. + // Android-changed: Use TLS 1.3 and 1.2 for testing + // TLS_SPEC_1_2 is used here. socket = createSocketWithEnabledProtocols(enabledSocketTlsVersions); connectionSpecSelector.configureSecureSocket(socket); - assertEnabledProtocols(socket, TlsVersion.TLS_1_0); + assertEnabledProtocols(socket, TlsVersion.TLS_1_2); retry = connectionSpecSelector.connectionFailed(RETRYABLE_EXCEPTION); assertFalse(retry); diff --git a/okhttp/src/main/java/com/squareup/okhttp/CipherSuite.java b/okhttp/src/main/java/com/squareup/okhttp/CipherSuite.java index 1334457..210f394 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/CipherSuite.java +++ b/okhttp/src/main/java/com/squareup/okhttp/CipherSuite.java @@ -225,6 +225,10 @@ public enum CipherSuite { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030, 5289, 8, 21), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031, 5289, 8, 21), TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032, 5289, 8, 21), + // Android-added: Android supported TLS 1.3 suites. + TLS_AES_128_GCM_SHA256("TLS_AES_128_GCM_SHA256", 0x1301, 8446, 11, 29), + TLS_AES_256_GCM_SHA384("TLS_AES_256_GCM_SHA384", 0x1302, 8446, 11, 29), + TLS_CHACHA20_POLY1305_SHA256("TLS_CHACHA20_POLY1305_SHA256", 0x1303, 8446, 11, 29), // TLS_ECDHE_PSK_WITH_RC4_128_SHA("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033, 5489, MAX_VALUE, MAX_VALUE), // TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034, 5489, MAX_VALUE, MAX_VALUE), // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0xc035, 5489, MAX_VALUE, MAX_VALUE), diff --git a/okhttp/src/main/java/com/squareup/okhttp/TlsVersion.java b/okhttp/src/main/java/com/squareup/okhttp/TlsVersion.java index 512aa0d..8c72dc0 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/TlsVersion.java +++ b/okhttp/src/main/java/com/squareup/okhttp/TlsVersion.java @@ -22,6 +22,7 @@ import javax.net.ssl.SSLSocket; * {@link SSLSocket#setEnabledProtocols}. */ public enum TlsVersion { + TLS_1_3("TLSv1.3"), // 2019. TLS_1_2("TLSv1.2"), // 2008. TLS_1_1("TLSv1.1"), // 2006. TLS_1_0("TLSv1"), // 1999. @@ -36,6 +37,7 @@ public enum TlsVersion { public static TlsVersion forJavaName(String javaName) { switch (javaName) { + case "TLSv1.3": return TLS_1_3; case "TLSv1.2": return TLS_1_2; case "TLSv1.1": return TLS_1_1; case "TLSv1": return TLS_1_0; diff --git a/repackaged/okhttp/src/main/java/com/android/okhttp/CipherSuite.java b/repackaged/okhttp/src/main/java/com/android/okhttp/CipherSuite.java index bc15fb7..644c59f 100644 --- a/repackaged/okhttp/src/main/java/com/android/okhttp/CipherSuite.java +++ b/repackaged/okhttp/src/main/java/com/android/okhttp/CipherSuite.java @@ -227,6 +227,10 @@ public enum CipherSuite { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030, 5289, 8, 21), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031, 5289, 8, 21), TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032, 5289, 8, 21), + // Android-added: Android supported TLS 1.3 suites. + TLS_AES_128_GCM_SHA256("TLS_AES_128_GCM_SHA256", 0x1301, 8446, 11, 29), + TLS_AES_256_GCM_SHA384("TLS_AES_256_GCM_SHA384", 0x1302, 8446, 11, 29), + TLS_CHACHA20_POLY1305_SHA256("TLS_CHACHA20_POLY1305_SHA256", 0x1303, 8446, 11, 29), // TLS_ECDHE_PSK_WITH_RC4_128_SHA("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033, 5489, MAX_VALUE, MAX_VALUE), // TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034, 5489, MAX_VALUE, MAX_VALUE), // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0xc035, 5489, MAX_VALUE, MAX_VALUE), diff --git a/repackaged/okhttp/src/main/java/com/android/okhttp/TlsVersion.java b/repackaged/okhttp/src/main/java/com/android/okhttp/TlsVersion.java index c8cd1e3..d9a6d9a 100644 --- a/repackaged/okhttp/src/main/java/com/android/okhttp/TlsVersion.java +++ b/repackaged/okhttp/src/main/java/com/android/okhttp/TlsVersion.java @@ -24,6 +24,7 @@ import javax.net.ssl.SSLSocket; * @hide This class is not part of the Android public SDK API */ public enum TlsVersion { + TLS_1_3("TLSv1.3"), // 2019. TLS_1_2("TLSv1.2"), // 2008. TLS_1_1("TLSv1.1"), // 2006. TLS_1_0("TLSv1"), // 1999. @@ -38,6 +39,7 @@ public enum TlsVersion { public static TlsVersion forJavaName(String javaName) { switch (javaName) { + case "TLSv1.3": return TLS_1_3; case "TLSv1.2": return TLS_1_2; case "TLSv1.1": return TLS_1_1; case "TLSv1": return TLS_1_0; |