/* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * @test * @summary This test will timeout if the ALPN CF is not completed * when a 'Connection reset by peer' exception is raised * during the handshake. * @bug 8217094 * @modules java.net.http * java.logging * @build ALPNFailureTest * @run main/othervm -Djdk.internal.httpclient.debug=true ALPNFailureTest HTTP_1_1 * @run main/othervm ALPNFailureTest HTTP_2
*/ import javax.net.ServerSocketFactory; import javax.net.ssl.SSLContext; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ProxySelector; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.StandardSocketOptions; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpTimeoutException; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference;
publicstaticvoid test(ServerSocket socket, SSLContext context,
ProxySelector ps, String... args) throws Exception
{
System.out.println("Tests a race condition in SSLTube/SSLFlowDelegate");
System.out.println("This test will timeout if the ALPN CF is not completed" + " when a 'Connection reset by peer' exception is raised" + " during the handshake - see 8217094.");
URI uri = new URI("https", null,
socket.getInetAddress().getHostAddress(), socket.getLocalPort(), "/ReadOnlyServer/https_1_1/", null, null);
HttpRequest request1 = HttpRequest.newBuilder(uri)
.GET().build();
HttpRequest request2 = HttpRequest.newBuilder(uri)
.POST(HttpRequest.BodyPublishers.ofString("foo")).build();
ReadOnlyServer server = new ReadOnlyServer(socket); Thread serverThread = newThread(server, "ServerThread");
serverThread.start(); try { for (var arg : args) { var version = HttpClient.Version.valueOf(arg);
HttpClient.Builder builder = HttpClient.newBuilder()
.version(version); if (ps != null) builder.proxy(ps); if (context != null) builder.sslContext(context);
HttpClient client = builder.build(); for (var request : List.of(request1, request2)) {
System.out.println("Server is " + socket.getLocalSocketAddress()
+ ", Version is " + version + ", Method is " + request.method()
+ (ps == null ? ", no proxy"
: (", Proxy is " + ps.select(request.uri())))); try {
HttpResponse<String> resp =
client.send(request, HttpResponse.BodyHandlers.ofString()); thrownew AssertionError( "Client should not have received any response: " + resp);
} catch (HttpTimeoutException x) {
System.out.println("Unexpected " + x);
x.printStackTrace(); thrownew AssertionError("Unexpected exception " + x, x);
} catch (Exception x) { // We expect IOException("Connection reset by peer"), but // any exception would do: we just don't want to linger // forever.
System.err.println("Client got expected exception: " + x);
x.printStackTrace(System.out);
}
}
}
} finally {
server.close();
}
}
publicstaticclass ReadOnlyServer implements Runnable, Closeable { final ServerSocket socket; final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final AtomicBoolean closing = new AtomicBoolean();
ReadOnlyServer(ServerSocket socket) { this.socket = socket;
}
@Override publicvoid run() { int count = 0; int all = 0; try {
System.out.println("Server starting"); while (!closing.get()) {
all += count;
count = 0; try (Socket client = socket.accept()) {
client.setSoTimeout(1000);
client.setOption(StandardSocketOptions.SO_LINGER, 0);
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream(); boolean drain = true; int timeouts = 0; // now read some byte from the ClientHello // and abruptly close the socket. while (drain) { try {
is.read();
count++; if (count >= 50) {
drain = false;
}
} catch (SocketTimeoutException so) { // make sure we read something if (count > 0) timeouts++; if (timeouts == 5) { // presumably the client is // waiting for us to answer... // but we should not reach here.
drain = false;
}
}
}
System.out.println("Got " + count + " bytes");
}
}
} catch (Throwable t) { if (!closing.get()) {
errorRef.set(t);
t.printStackTrace();
}
} finally {
System.out.println("Server existing after reading " + (all + count) + " bytes");
close();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.