From 0ef34e3bab9e8600cab153264886f0026d8f3a13 Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Fri, 15 Dec 2023 18:21:45 +0000 Subject: [PATCH 1/8] Backport of 2e31cc7ee1b875af7c7b3a5367ac8056fbc60650 --- .../sun/net/www/http/KeepAliveCache.java | 130 +++++++++--------- 1 file changed, 64 insertions(+), 66 deletions(-) diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java index 16f02d7cdde..d6548e0c531 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2017, 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 @@ -27,9 +27,17 @@ import java.io.IOException; import java.io.NotSerializableException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashMap; -import java.net.URL; +import java.util.List; + +import sun.security.action.GetIntegerAction; /** * A class that implements a cache of idle Http connections for keep-alive @@ -52,14 +60,14 @@ public class KeepAliveCache static int result = -1; static int getMaxConnections() { if (result == -1) { - result = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction("http.maxConnections", - MAX_CONNECTIONS)) + result = AccessController.doPrivileged( + new GetIntegerAction("http.maxConnections", MAX_CONNECTIONS)) .intValue(); - if (result <= 0) + if (result <= 0) { result = MAX_CONNECTIONS; + } } - return result; + return result; } static final int LIFETIME = 5000; @@ -92,8 +100,7 @@ public synchronized void put(final URL url, Object obj, HttpClient http) { * The robustness to get around this is in HttpClient.parseHTTP() */ final KeepAliveCache cache = this; - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction() { public Void run() { // We want to create the Keep-Alive-Timer in the // system threadgroup @@ -120,8 +127,8 @@ public Void run() { if (v == null) { int keepAliveTimeout = http.getKeepAliveTimeout(); - v = new ClientVector(keepAliveTimeout > 0? - keepAliveTimeout*1000 : LIFETIME); + v = new ClientVector(keepAliveTimeout > 0 ? + keepAliveTimeout * 1000 : LIFETIME); v.put(http); super.put(key, v); } else { @@ -130,12 +137,12 @@ public Void run() { } /* remove an obsolete HttpClient from its VectorCache */ - public synchronized void remove (HttpClient h, Object obj) { + public synchronized void remove(HttpClient h, Object obj) { KeepAliveKey key = new KeepAliveKey(h.url, obj); ClientVector v = super.get(key); if (v != null) { v.remove(h); - if (v.empty()) { + if (v.isEmpty()) { removeVector(key); } } @@ -171,39 +178,27 @@ public void run() { try { Thread.sleep(LIFETIME); } catch (InterruptedException e) {} - synchronized (this) { - /* Remove all unused HttpClients. Starting from the - * bottom of the stack (the least-recently used first). - * REMIND: It'd be nice to not remove *all* connections - * that aren't presently in use. One could have been added - * a second ago that's still perfectly valid, and we're - * needlessly axing it. But it's not clear how to do this - * cleanly, and doing it right may be more trouble than it's - * worth. - */ + // Remove all outdated HttpClients. + synchronized (this) { long currentTime = System.currentTimeMillis(); - - ArrayList keysToRemove - = new ArrayList(); + List keysToRemove = new ArrayList<>(); for (KeepAliveKey key : keySet()) { ClientVector v = get(key); synchronized (v) { - int i; - - for (i = 0; i < v.size(); i++) { - KeepAliveEntry e = v.elementAt(i); + KeepAliveEntry e = v.peek(); + while (e != null) { if ((currentTime - e.idleStartTime) > v.nap) { - HttpClient h = e.hc; - h.closeServer(); + v.poll(); + e.hc.closeServer(); } else { break; } + e = v.peek(); } - v.subList(0, i).clear(); - if (v.size() == 0) { + if (v.isEmpty()) { keysToRemove.add(key); } } @@ -213,21 +208,19 @@ public void run() { removeVector(key); } } - } while (size() > 0); - - return; + } while (!isEmpty()); } /* * Do not serialize this class! */ - private void writeObject(java.io.ObjectOutputStream stream) - throws IOException { + private void writeObject(ObjectOutputStream stream) throws IOException { throw new NotSerializableException(); } - private void readObject(java.io.ObjectInputStream stream) - throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { throw new NotSerializableException(); } } @@ -235,37 +228,33 @@ private void readObject(java.io.ObjectInputStream stream) /* FILO order for recycling HttpClients, should run in a thread * to time them out. If > maxConns are in use, block. */ - - -class ClientVector extends java.util.Stack { +class ClientVector extends ArrayDeque { private static final long serialVersionUID = -8680532108106489459L; // sleep time in milliseconds, before cache clear int nap; - - - ClientVector (int nap) { + ClientVector(int nap) { this.nap = nap; } synchronized HttpClient get() { - if (empty()) { + if (isEmpty()) { return null; - } else { - // Loop until we find a connection that has not timed out - HttpClient hc = null; - long currentTime = System.currentTimeMillis(); - do { - KeepAliveEntry e = pop(); - if ((currentTime - e.idleStartTime) > nap) { - e.hc.closeServer(); - } else { - hc = e.hc; - } - } while ((hc== null) && (!empty())); - return hc; } + + // Loop until we find a connection that has not timed out + HttpClient hc = null; + long currentTime = System.currentTimeMillis(); + do { + KeepAliveEntry e = pop(); + if ((currentTime - e.idleStartTime) > nap) { + e.hc.closeServer(); + } else { + hc = e.hc; + } + } while ((hc == null) && (!isEmpty())); + return hc; } /* return a still valid, unused HttpClient */ @@ -277,21 +266,30 @@ synchronized void put(HttpClient h) { } } + /* remove an HttpClient */ + synchronized boolean remove(HttpClient h) { + for (KeepAliveEntry curr : this) { + if (curr.hc == h) { + return super.remove(curr); + } + } + return false; + } + /* * Do not serialize this class! */ - private void writeObject(java.io.ObjectOutputStream stream) - throws IOException { + private void writeObject(ObjectOutputStream stream) throws IOException { throw new NotSerializableException(); } - private void readObject(java.io.ObjectInputStream stream) - throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { throw new NotSerializableException(); } } - class KeepAliveKey { private String protocol = null; private String host = null; From 0d51b250125656925e335ee162ff23005fddf761 Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Mon, 18 Dec 2023 19:00:56 +0000 Subject: [PATCH 2/8] Backport 770c1f65c588f3156f9b70097df752d8059c1038 --- .../sun/net/www/http/KeepAliveCache.java | 84 ++++--- .../net/www/protocol/https/HttpsClient.java | 8 + .../net/www/http/KeepAliveCache/B8293562.java | 238 ++++++++++++++++++ 3 files changed, 299 insertions(+), 31 deletions(-) create mode 100644 jdk/test/sun/net/www/http/KeepAliveCache/B8293562.java diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java index d6548e0c531..f964e61f4d2 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -84,7 +84,14 @@ public KeepAliveCache() {} * @param url The URL contains info about the host and port * @param http The HttpClient to be cached */ - public synchronized void put(final URL url, Object obj, HttpClient http) { + public void put(final URL url, Object obj, HttpClient http) { + // this method may need to close an HttpClient, either because + // it is not cacheable, or because the cache is at its capacity. + // In the latter case, we close the least recently used client. + // The client to close is stored in oldClient, and is closed + // after cacheLock is released. + HttpClient oldClient = null; + synchronized (this) { boolean startThread = (keepAliveTimer == null); if (!startThread) { if (!keepAliveTimer.isAlive()) { @@ -132,7 +139,12 @@ public Void run() { v.put(http); super.put(key, v); } else { - v.put(http); + oldClient = v.put(http); + } + } + // close after releasing locks + if (oldClient != null) { + oldClient.closeServer(); } } @@ -159,7 +171,6 @@ synchronized void removeVector(KeepAliveKey k) { * Check to see if this URL has a cached HttpClient */ public synchronized HttpClient get(URL url, Object obj) { - KeepAliveKey key = new KeepAliveKey(url, obj); ClientVector v = super.get(key); if (v == null) { // nothing in cache yet @@ -178,6 +189,7 @@ public void run() { try { Thread.sleep(LIFETIME); } catch (InterruptedException e) {} + List closeList = null; // Remove all outdated HttpClients. synchronized (this) { @@ -187,15 +199,18 @@ public void run() { for (KeepAliveKey key : keySet()) { ClientVector v = get(key); synchronized (v) { - KeepAliveEntry e = v.peek(); + KeepAliveEntry e = v.peekLast(); while (e != null) { if ((currentTime - e.idleStartTime) > v.nap) { - v.poll(); - e.hc.closeServer(); + v.pollLast(); + if (closeList == null) { + closeList = new ArrayList<>(); + } + closeList.add(e.hc); } else { break; } - e = v.peek(); + e = v.peekLast(); } if (v.isEmpty()) { @@ -208,6 +223,12 @@ public void run() { removeVector(key); } } + // close connections outside cacheLock + if (closeList != null) { + for (HttpClient hc : closeList) { + hc.closeServer(); + } + } } while (!isEmpty()); } @@ -225,8 +246,8 @@ private void readObject(ObjectInputStream stream) } } -/* FILO order for recycling HttpClients, should run in a thread - * to time them out. If > maxConns are in use, block. +/* LIFO order for reusing HttpClients. Most recent entries at the front. + * If > maxConns are in use, discard oldest. */ class ClientVector extends ArrayDeque { private static final long serialVersionUID = -8680532108106489459L; @@ -239,34 +260,35 @@ class ClientVector extends ArrayDeque { } synchronized HttpClient get() { - if (isEmpty()) { + // check the most recent connection, use if still valid + KeepAliveEntry e = peekFirst(); + if (e == null) { return null; } - // Loop until we find a connection that has not timed out - HttpClient hc = null; long currentTime = System.currentTimeMillis(); - do { - KeepAliveEntry e = pop(); if ((currentTime - e.idleStartTime) > nap) { - e.hc.closeServer(); - } else { - hc = e.hc; - } - } while ((hc == null) && (!isEmpty())); - return hc; + return null; // all connections stale - will be cleaned up later + } else { + pollFirst(); + return e.hc; + } } /* return a still valid, unused HttpClient */ - synchronized void put(HttpClient h) { + synchronized HttpClient put(HttpClient h) { + HttpClient staleClient = null; + assert KeepAliveCache.getMaxConnections() > 0; if (size() >= KeepAliveCache.getMaxConnections()) { - h.closeServer(); // otherwise the connection remains in limbo - } else { - push(new KeepAliveEntry(h, System.currentTimeMillis())); + // remove oldest connection + staleClient = removeLast().hc; } + addFirst(new KeepAliveEntry(h, System.currentTimeMillis())); + // close after releasing the locks + return staleClient; } - /* remove an HttpClient */ +/* remove an HttpClient */ synchronized boolean remove(HttpClient h) { for (KeepAliveEntry curr : this) { if (curr.hc == h) { @@ -291,10 +313,10 @@ private void readObject(ObjectInputStream stream) } class KeepAliveKey { - private String protocol = null; - private String host = null; - private int port = 0; - private Object obj = null; // additional key, such as socketfactory + private final String protocol; + private final String host; + private final int port; + private final Object obj; // additional key, such as socketfactory /** * Constructor @@ -335,8 +357,8 @@ public int hashCode() { } class KeepAliveEntry { - HttpClient hc; - long idleStartTime; + final HttpClient hc; + final long idleStartTime; KeepAliveEntry(HttpClient hc, long idleStartTime) { this.hc = hc; diff --git a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java index 98e3fcc3213..590c04e4223 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -419,6 +419,14 @@ protected Socket createSocket() throws IOException { } } + @Override + public void closeServer() { + try { + // SSLSocket.close may block up to timeout. Make sure it's short. + serverSocket.setSoTimeout(1); + } catch (Exception e) {} + super.closeServer(); + } @Override public boolean needsTunneling() { diff --git a/jdk/test/sun/net/www/http/KeepAliveCache/B8293562.java b/jdk/test/sun/net/www/http/KeepAliveCache/B8293562.java new file mode 100644 index 00000000000..4e0cff8bab4 --- /dev/null +++ b/jdk/test/sun/net/www/http/KeepAliveCache/B8293562.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2022, 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 + * @bug 8293562 + * @library /test/lib + * @run main/othervm -Dhttp.keepAlive.time.server=1 B8293562 + * @summary Http keep-alive thread should close sockets without holding a lock + */ + +import com.sun.net.httpserver.HttpServer; + +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class B8293562 { + static HttpServer server; + static CountDownLatch closing = new CountDownLatch(1); + static CountDownLatch secondRequestDone = new CountDownLatch(1); + static CompletableFuture result = new CompletableFuture<>(); + + public static void main(String[] args) throws Exception { + startHttpServer(); + clientHttpCalls(); + } + + public static void startHttpServer() throws Exception { + server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 10); + server.setExecutor(Executors.newCachedThreadPool()); + server.start(); + } + + public static void clientHttpCalls() throws Exception { + try { + System.out.println("http server listen on: " + server.getAddress().getPort()); + String hostAddr = InetAddress.getLoopbackAddress().getHostAddress(); + if (hostAddr.indexOf(':') > -1) hostAddr = "[" + hostAddr + "]"; + String baseURLStr = "https://" + hostAddr + ":" + server.getAddress().getPort() + "/"; + + URL testUrl = new URL (baseURLStr); + + // SlowCloseSocketFactory is not a real SSLSocketFactory; + // it produces regular non-SSL sockets. Effectively, the request + // is made over http. + HttpsURLConnection.setDefaultSSLSocketFactory(new SlowCloseSocketFactory()); + System.out.println("Performing first request"); + HttpsURLConnection uc = (HttpsURLConnection)testUrl.openConnection(Proxy.NO_PROXY); + byte[] buf = new byte[1024]; + try { + uc.getInputStream(); + throw new RuntimeException("Expected 404 here"); + } catch (FileNotFoundException ignored) { } + try (InputStream is = uc.getErrorStream()) { + while (is.read(buf) >= 0) { + } + } + System.out.println("First request completed"); + closing.await(); + // KeepAliveThread is closing the connection now + System.out.println("Performing second request"); + HttpsURLConnection uc2 = (HttpsURLConnection)testUrl.openConnection(Proxy.NO_PROXY); + + try { + uc2.getInputStream(); + throw new RuntimeException("Expected 404 here"); + } catch (FileNotFoundException ignored) { } + try (InputStream is = uc2.getErrorStream()) { + while (is.read(buf) >= 0) { + } + } + System.out.println("Second request completed"); + // let the socket know it can close now + secondRequestDone.countDown(); + result.get(); + System.out.println("Test completed successfully"); + } finally { + server.stop(1); + } + } + + static class SlowCloseSocket extends SSLSocket { + @Override + public synchronized void close() throws IOException { + String threadName = Thread.currentThread().getName(); + System.out.println("Connection closing, thread name: " + threadName); + closing.countDown(); + super.close(); + if (threadName.equals("Keep-Alive-Timer")) { + try { + if (secondRequestDone.await(5, TimeUnit.SECONDS)) { + result.complete(null); + } else { + result.completeExceptionally(new RuntimeException( + "Wait for second request timed out")); + } + } catch (InterruptedException e) { + result.completeExceptionally(new RuntimeException( + "Wait for second request was interrupted")); + } + } else { + result.completeExceptionally(new RuntimeException( + "Close invoked from unexpected thread")); + } + System.out.println("Connection closed"); + } + + // required abstract method overrides + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public String[] getEnabledCipherSuites() { + return new String[0]; + } + @Override + public void setEnabledCipherSuites(String[] suites) { } + @Override + public String[] getSupportedProtocols() { + return new String[0]; + } + @Override + public String[] getEnabledProtocols() { + return new String[0]; + } + @Override + public void setEnabledProtocols(String[] protocols) { } + @Override + public SSLSession getSession() { + return null; + } + @Override + public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void startHandshake() throws IOException { } + @Override + public void setUseClientMode(boolean mode) { } + @Override + public boolean getUseClientMode() { + return false; + } + @Override + public void setNeedClientAuth(boolean need) { } + @Override + public boolean getNeedClientAuth() { + return false; + } + @Override + public void setWantClientAuth(boolean want) { } + @Override + public boolean getWantClientAuth() { + return false; + } + @Override + public void setEnableSessionCreation(boolean flag) { } + @Override + public boolean getEnableSessionCreation() { + return false; + } + } + + static class SlowCloseSocketFactory extends SSLSocketFactory { + + @Override + public Socket createSocket() throws IOException { + return new SlowCloseSocket(); + } + // required abstract method overrides + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public String[] getDefaultCipherSuites() { + return new String[0]; + } + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + throw new UnsupportedOperationException(); + } + } +} + From 7d73c521b43bbe1a7dad827c6f6ec28da3da1ec0 Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Wed, 31 Jan 2024 05:04:32 +0000 Subject: [PATCH 3/8] Fix indentation --- .../sun/net/www/http/KeepAliveCache.java | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java index f964e61f4d2..7bfba915c94 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -92,56 +92,56 @@ public void put(final URL url, Object obj, HttpClient http) { // after cacheLock is released. HttpClient oldClient = null; synchronized (this) { - boolean startThread = (keepAliveTimer == null); - if (!startThread) { - if (!keepAliveTimer.isAlive()) { - startThread = true; + boolean startThread = (keepAliveTimer == null); + if (!startThread) { + if (!keepAliveTimer.isAlive()) { + startThread = true; + } } - } - if (startThread) { - clear(); - /* Unfortunately, we can't always believe the keep-alive timeout we got - * back from the server. If I'm connected through a Netscape proxy - * to a server that sent me a keep-alive - * time of 15 sec, the proxy unilaterally terminates my connection - * The robustness to get around this is in HttpClient.parseHTTP() - */ - final KeepAliveCache cache = this; - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - // We want to create the Keep-Alive-Timer in the - // system threadgroup - ThreadGroup grp = Thread.currentThread().getThreadGroup(); - ThreadGroup parent = null; - while ((parent = grp.getParent()) != null) { - grp = parent; + if (startThread) { + clear(); + /* Unfortunately, we can't always believe the keep-alive timeout we got + * back from the server. If I'm connected through a Netscape proxy + * to a server that sent me a keep-alive + * time of 15 sec, the proxy unilaterally terminates my connection + * The robustness to get around this is in HttpClient.parseHTTP() + */ + final KeepAliveCache cache = this; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + // We want to create the Keep-Alive-Timer in the + // system threadgroup + ThreadGroup grp = Thread.currentThread().getThreadGroup(); + ThreadGroup parent = null; + while ((parent = grp.getParent()) != null) { + grp = parent; + } + + keepAliveTimer = new Thread(grp, cache, "Keep-Alive-Timer"); + keepAliveTimer.setDaemon(true); + keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2); + // Set the context class loader to null in order to avoid + // keeping a strong reference to an application classloader. + keepAliveTimer.setContextClassLoader(null); + keepAliveTimer.start(); + return null; } + }); + } - keepAliveTimer = new Thread(grp, cache, "Keep-Alive-Timer"); - keepAliveTimer.setDaemon(true); - keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2); - // Set the context class loader to null in order to avoid - // keeping a strong reference to an application classloader. - keepAliveTimer.setContextClassLoader(null); - keepAliveTimer.start(); - return null; - } - }); - } + KeepAliveKey key = new KeepAliveKey(url, obj); + ClientVector v = super.get(key); - KeepAliveKey key = new KeepAliveKey(url, obj); - ClientVector v = super.get(key); - - if (v == null) { - int keepAliveTimeout = http.getKeepAliveTimeout(); - v = new ClientVector(keepAliveTimeout > 0 ? - keepAliveTimeout * 1000 : LIFETIME); - v.put(http); - super.put(key, v); - } else { + if (v == null) { + int keepAliveTimeout = http.getKeepAliveTimeout(); + v = new ClientVector(keepAliveTimeout > 0 ? + keepAliveTimeout * 1000 : LIFETIME); + v.put(http); + super.put(key, v); + } else { oldClient = v.put(http); + } } - } // close after releasing locks if (oldClient != null) { oldClient.closeServer(); @@ -225,10 +225,10 @@ public void run() { } // close connections outside cacheLock if (closeList != null) { - for (HttpClient hc : closeList) { - hc.closeServer(); - } - } + for (HttpClient hc : closeList) { + hc.closeServer(); + } + } } while (!isEmpty()); } @@ -267,7 +267,7 @@ synchronized HttpClient get() { } long currentTime = System.currentTimeMillis(); - if ((currentTime - e.idleStartTime) > nap) { + if ((currentTime - e.idleStartTime) > nap) { return null; // all connections stale - will be cleaned up later } else { pollFirst(); @@ -288,7 +288,7 @@ synchronized HttpClient put(HttpClient h) { return staleClient; } -/* remove an HttpClient */ + /* remove an HttpClient */ synchronized boolean remove(HttpClient h) { for (KeepAliveEntry curr : this) { if (curr.hc == h) { From 80387afdc411013250ba65d22cfc1bc0e5021fda Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Wed, 7 Feb 2024 16:51:41 +0000 Subject: [PATCH 4/8] Backport d8f44aa39e921594505864e6270f42b745265293 --- .../java/net/doc-files/net-properties.html | 10 + .../classes/sun/net/www/http/HttpClient.java | 20 +- .../sun/net/www/http/KeepAliveCache.java | 65 ++++++- .../KeepAliveCache/KeepAliveProperty.java | 178 ++++++++++++++++++ 4 files changed, 261 insertions(+), 12 deletions(-) create mode 100644 jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveProperty.java diff --git a/jdk/src/share/classes/java/net/doc-files/net-properties.html b/jdk/src/share/classes/java/net/doc-files/net-properties.html index 5aac0c8e3bd..b2c9430fb6c 100644 --- a/jdk/src/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html @@ -172,6 +172,16 @@

Misc HTTP properties

If HTTP keepalive is enabled (see above) this value determines the maximum number of idle connections that will be simultaneously kept alive, per destination.

+
  • {@systemProperty http.keepAlive.time.server} and + {@systemProperty http.keepAlive.time.proxy}

    +

    These properties modify the behavior of the HTTP keepalive cache in the case + where the server (or proxy) has not specified a keepalive time. If the + property is set in this case, then idle connections will be closed after the + specified number of seconds. If the property is set, and the server does + specify a keepalive time in a "Keep-Alive" response header, then the time specified + by the server is used. If the property is not set and also the server + does not specify a keepalive time, then connections are kept alive for an + implementation defined time, assuming {@code http.keepAlive} is {@code true}.

  • http.maxRedirects (default: 20)
    This integer value determines the maximum number, for a given request, of HTTP redirects that will be automatically followed by the diff --git a/jdk/src/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/share/classes/sun/net/www/http/HttpClient.java index dd6384efe88..ffb26c07c13 100644 --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java @@ -114,13 +114,13 @@ static private int getDefaultPort(String proto) { recomputing the value of keepingAlive */ int keepAliveConnections = -1; /* number of keep-alives left */ - /**Idle timeout value, in milliseconds. Zero means infinity, - * iff keepingAlive=true. - * Unfortunately, we can't always believe this one. If I'm connected - * through a Netscape proxy to a server that sent me a keep-alive - * time of 15 sec, the proxy unilaterally terminates my connection - * after 5 sec. So we have to hard code our effective timeout to - * 4 sec for the case where we're using a proxy. *SIGH* + /* + * The timeout if specified by the server. Following values possible + * 0: the server specified no keep alive headers + * -1: the server provided "Connection: keep-alive" but did not specify a + * a particular time in a "Keep-Alive:" headers + * Positive values are the number of seconds specified by the server + * in a "Keep-Alive" header */ int keepAliveTimeout = 0; @@ -816,7 +816,7 @@ private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, Http responses.findValue("Keep-Alive")); /* default should be larger in case of proxy */ keepAliveConnections = p.findInt("max", usingProxy?50:5); - keepAliveTimeout = p.findInt("timeout", usingProxy?60:5); + keepAliveTimeout = p.findInt("timeout", -1); } } else if (b[7] != '0') { /* @@ -1070,6 +1070,10 @@ public String getProxyHostUsed() { } } + public boolean getUsingProxy() { + return usingProxy; + } + /** * @return the proxy port being used for this client. Meaningless * if getProxyHostUsed() gives null. diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java index d6548e0c531..9c255930720 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -38,6 +38,8 @@ import java.util.List; import sun.security.action.GetIntegerAction; +import sun.net.www.protocol.http.HttpURLConnection; +import sun.util.logging.PlatformLogger; /** * A class that implements a cache of idle Http connections for keep-alive @@ -50,6 +52,32 @@ public class KeepAliveCache implements Runnable { private static final long serialVersionUID = -2937172892064557949L; + // Keep alive time set according to priority specified here: + // 1. If server specifies a time with a Keep-Alive header + // 2. If user specifies a time with system property below + // 3. Default values which depend on proxy vs server and whether + // a Connection: keep-alive header was sent by server + + // name suffixed with "server" or "proxy" + private static final String keepAliveProp = "http.keepAlive.time."; + + private static final int userKeepAliveServer; + private static final int userKeepAliveProxy; + + static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); + + @SuppressWarnings("removal") + static int getUserKeepAliveSeconds(String type) { + int v = AccessController.doPrivileged( + new GetIntegerAction(keepAliveProp+type, -1)).intValue(); + return v < -1 ? -1 : v; + } + + static { + userKeepAliveServer = getUserKeepAliveSeconds("server"); + userKeepAliveProxy = getUserKeepAliveSeconds("proxy"); + } + /* maximum # keep-alive connections to maintain at once * This should be 2 by the HTTP spec, but because we don't support pipe-lining * a larger value is more appropriate. So we now set a default of 5, and the value @@ -127,15 +155,39 @@ public Void run() { if (v == null) { int keepAliveTimeout = http.getKeepAliveTimeout(); - v = new ClientVector(keepAliveTimeout > 0 ? - keepAliveTimeout * 1000 : LIFETIME); - v.put(http); - super.put(key, v); + if (keepAliveTimeout == 0) { + keepAliveTimeout = getUserKeepAlive(http.getUsingProxy()); + if (keepAliveTimeout == -1) { + // same default for server and proxy + keepAliveTimeout = 5; + } + } else if (keepAliveTimeout == -1) { + keepAliveTimeout = getUserKeepAlive(http.getUsingProxy()); + if (keepAliveTimeout == -1) { + // different default for server and proxy + keepAliveTimeout = http.getUsingProxy() ? 60 : 5; + } + } + // at this point keepAliveTimeout is the number of seconds to keep + // alive, which could be 0, if the user specified 0 for the property + assert keepAliveTimeout >= 0; + if (keepAliveTimeout == 0) { + http.closeServer(); + } else { + v = new ClientVector(keepAliveTimeout * 1000); + v.put(http); + super.put(key, v); + } } else { v.put(http); } } + // returns the keep alive set by user in system property or -1 if not set + private static int getUserKeepAlive(boolean isProxy) { + return isProxy ? userKeepAliveProxy : userKeepAliveServer; + } + /* remove an obsolete HttpClient from its VectorCache */ public synchronized void remove(HttpClient h, Object obj) { KeepAliveKey key = new KeepAliveKey(h.url, obj); @@ -252,6 +304,11 @@ synchronized HttpClient get() { e.hc.closeServer(); } else { hc = e.hc; + if (KeepAliveCache.logger.isLoggable(PlatformLogger.Level.FINEST)) { + String msg = "cached HttpClient was idle for " + + Long.toString(currentTime - e.idleStartTime); + KeepAliveCache.logger.finest(msg); + } } } while ((hc == null) && (!isEmpty())); return hc; diff --git a/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveProperty.java b/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveProperty.java new file mode 100644 index 00000000000..afea35e48b7 --- /dev/null +++ b/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveProperty.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2022, 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 + * @library /lib/testlibrary + * @bug 8278067 + * @run main/othervm -Dhttp.keepAlive.time.server=30 KeepAliveProperty long + * @run main/othervm -Dhttp.keepAlive.time.server=1 KeepAliveProperty short + * @run main/othervm -ea -Dhttp.keepAlive.time.server=0 KeepAliveProperty short + */ + +import java.net.*; +import java.io.*; +import java.nio.charset.*; +import java.util.logging.*; +import jdk.testlibrary.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; + +public class KeepAliveProperty { + + static volatile boolean pass = false; + + static class Server extends Thread { + final ServerSocket server; + + Server (ServerSocket server) { + super (); + this.server = server; + } + + void readAll (Socket s) throws IOException { + byte[] buf = new byte [128]; + int c; + String request = ""; + InputStream is = s.getInputStream (); + while ((c=is.read(buf)) > 0) { + request += new String(buf, 0, c, StandardCharsets.US_ASCII); + if (request.contains("\r\n\r\n")) { + return; + } + } + if (c == -1) + throw new IOException("Socket closed"); + } + + Socket s = null; + String BODY; + String CLEN; + PrintStream out; + + public void run() { + try { + s = server.accept(); + readAll(s); + + BODY = "Hello world"; + CLEN = "Content-Length: " + BODY.length() + "\r\n"; + out = new PrintStream(new BufferedOutputStream(s.getOutputStream() )); + + /* send the header */ + out.print("HTTP/1.1 200 OK\r\n"); + out.print("Content-Type: text/plain; charset=iso-8859-1\r\n"); + out.print(CLEN); + out.print("\r\n"); + out.print(BODY); + out.flush(); + } catch (Exception e) { + pass = false; + try { + if (s != null) + s.close(); + server.close(); + } catch (IOException unused) {} + return; + } + + // second request may legitimately fail + + try (Socket s2 = s; ServerSocket server2 = server; PrintStream out2 = out) { + // wait for second request. + readAll(s2); + + BODY = "Goodbye world"; + CLEN = "Content-Length: " + BODY.length() + "\r\n"; + + /* send the header */ + out2.print("HTTP/1.1 200 OK\r\n"); + out2.print("Content-Type: text/plain; charset=iso-8859-1\r\n"); + out2.print(CLEN); + out2.print("\r\n"); + out2.print(BODY); + out2.flush(); + pass = !expectClose; + if (!pass) System.out.println("Failed: expected close"); + } catch (Exception e) { + pass = expectClose; + if (!pass) System.out.println("Failed: did not expect close"); + } + } + } + + static String fetch(URL url) throws Exception { + InputStream in = url.openConnection(NO_PROXY).getInputStream(); + String s = ""; + byte b[] = new byte[128]; + int n; + do { + n = in.read(b); + if (n > 0) + s += new String(b, 0, n, StandardCharsets.US_ASCII); + } while (n > 0); + in.close(); + return s; + } + + static volatile boolean expectClose; + + public static void main(String args[]) throws Exception { + // exercise the logging code + Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); + logger.setLevel(Level.FINEST); + ConsoleHandler h = new ConsoleHandler(); + h.setLevel(Level.FINEST); + logger.addHandler(h); + + expectClose = args[0].equals("short"); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ServerSocket ss = new ServerSocket(); + ss.bind(new InetSocketAddress(loopback, 0)); + Server s = new Server(ss); + s.start(); + + URL url = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(ss.getLocalPort()) + .toURL(); + System.out.println("URL: " + url); + + if (!fetch(url).equals("Hello world")) + throw new RuntimeException("Failed on first request"); + + // Wait a while to see if connection is closed + Thread.sleep(3 * 1000); + + try { + if (!fetch(url).equals("Goodbye world")) + throw new RuntimeException("Failed on second request"); + } catch (Exception e) { + if (!expectClose) + throw e; + } + + if (!pass) + throw new RuntimeException("Failed in server"); + } +} From 22fb611bfab8a41a7b431efa77c539a21c838b4b Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Wed, 7 Feb 2024 17:07:27 +0000 Subject: [PATCH 5/8] Fix indentation --- .../java/net/doc-files/net-properties.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/java/net/doc-files/net-properties.html b/jdk/src/share/classes/java/net/doc-files/net-properties.html index b2c9430fb6c..984ea568329 100644 --- a/jdk/src/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html @@ -173,15 +173,15 @@

    Misc HTTP properties

    maximum number of idle connections that will be simultaneously kept alive, per destination.

  • {@systemProperty http.keepAlive.time.server} and - {@systemProperty http.keepAlive.time.proxy}

    + {@systemProperty http.keepAlive.time.proxy}

    These properties modify the behavior of the HTTP keepalive cache in the case - where the server (or proxy) has not specified a keepalive time. If the - property is set in this case, then idle connections will be closed after the - specified number of seconds. If the property is set, and the server does - specify a keepalive time in a "Keep-Alive" response header, then the time specified - by the server is used. If the property is not set and also the server - does not specify a keepalive time, then connections are kept alive for an - implementation defined time, assuming {@code http.keepAlive} is {@code true}.

    + where the server (or proxy) has not specified a keepalive time. If the + property is set in this case, then idle connections will be closed after the + specified number of seconds. If the property is set, and the server does + specify a keepalive time in a "Keep-Alive" response header, then the time specified + by the server is used. If the property is not set and also the server + does not specify a keepalive time, then connections are kept alive for an + implementation defined time, assuming {@code http.keepAlive} is {@code true}.

  • http.maxRedirects (default: 20)
    This integer value determines the maximum number, for a given request, of HTTP redirects that will be automatically followed by the From f44e27bae66f675250fa7177d7a7dda73ce1431c Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Tue, 20 Feb 2024 23:56:45 +0000 Subject: [PATCH 6/8] Remove SystemProperty tag as it is not supported in JDK8 --- jdk/src/share/classes/java/net/doc-files/net-properties.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/net/doc-files/net-properties.html b/jdk/src/share/classes/java/net/doc-files/net-properties.html index 984ea568329..d5dc6b0c2f8 100644 --- a/jdk/src/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html @@ -172,8 +172,8 @@

    Misc HTTP properties

    If HTTP keepalive is enabled (see above) this value determines the maximum number of idle connections that will be simultaneously kept alive, per destination.

    -
  • {@systemProperty http.keepAlive.time.server} and - {@systemProperty http.keepAlive.time.proxy}

    +
  • http.keepAlive.time.server and + http.keepAlive.time.proxy

    These properties modify the behavior of the HTTP keepalive cache in the case where the server (or proxy) has not specified a keepalive time. If the property is set in this case, then idle connections will be closed after the From 910316f66abfba704387fe3bc8ba05d8bbe08020 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 29 Mar 2023 07:27:06 +0000 Subject: [PATCH 7/8] 8291226: Create Test Cases to cover scenarios for JDK-8278067 Backport-of: 86ec158dfb7a770fe9a74ff8617bac938d0bb90f --- .../www/http/HttpClient/KeepAliveTest.java | 1277 +++++++++++++++++ 1 file changed, 1277 insertions(+) create mode 100644 jdk/test/sun/net/www/http/HttpClient/KeepAliveTest.java diff --git a/jdk/test/sun/net/www/http/HttpClient/KeepAliveTest.java b/jdk/test/sun/net/www/http/HttpClient/KeepAliveTest.java new file mode 100644 index 00000000000..7ec12a279b4 --- /dev/null +++ b/jdk/test/sun/net/www/http/HttpClient/KeepAliveTest.java @@ -0,0 +1,1277 @@ +/* + * Copyright (c) 2022 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 + * @library /test/lib + * @modules java.base/sun.net:+open + * java.base/sun.net.www.http:+open + * java.base/sun.net.www:+open + * java.base/sun.net.www.protocol.http:+open + * @run main/othervm KeepAliveTest 0 + * @run main/othervm KeepAliveTest 1 + * @run main/othervm KeepAliveTest 2 + * @run main/othervm KeepAliveTest 3 + * @run main/othervm KeepAliveTest 4 + * @run main/othervm KeepAliveTest 5 + * @run main/othervm KeepAliveTest 6 + * @run main/othervm KeepAliveTest 7 + * @run main/othervm KeepAliveTest 8 + * @run main/othervm KeepAliveTest 9 + * @run main/othervm KeepAliveTest 10 + * @run main/othervm KeepAliveTest 11 + * @run main/othervm KeepAliveTest 12 + * @run main/othervm KeepAliveTest 13 + * @run main/othervm KeepAliveTest 14 + * @run main/othervm KeepAliveTest 15 + * @run main/othervm KeepAliveTest 16 + * @run main/othervm KeepAliveTest 17 + * @run main/othervm KeepAliveTest 18 + * @run main/othervm KeepAliveTest 19 + * @run main/othervm KeepAliveTest 20 + * @run main/othervm KeepAliveTest 21 + * @run main/othervm KeepAliveTest 22 + * @run main/othervm KeepAliveTest 23 + * @run main/othervm KeepAliveTest 24 + * @run main/othervm KeepAliveTest 25 + * @run main/othervm KeepAliveTest 26 + * @run main/othervm KeepAliveTest 27 + * @run main/othervm KeepAliveTest 28 + * @run main/othervm KeepAliveTest 29 + * @run main/othervm KeepAliveTest 30 + * @run main/othervm KeepAliveTest 31 + * @run main/othervm KeepAliveTest 32 + * @run main/othervm KeepAliveTest 33 + * @run main/othervm KeepAliveTest 34 + * @run main/othervm KeepAliveTest 35 + * @run main/othervm KeepAliveTest 36 + * @run main/othervm KeepAliveTest 37 + * @run main/othervm KeepAliveTest 38 + * @run main/othervm KeepAliveTest 39 + * @run main/othervm KeepAliveTest 40 + * @run main/othervm KeepAliveTest 41 + * @run main/othervm KeepAliveTest 42 + * @run main/othervm KeepAliveTest 43 + * @run main/othervm KeepAliveTest 44 + * @run main/othervm KeepAliveTest 45 + * @run main/othervm KeepAliveTest 46 + * @run main/othervm KeepAliveTest 47 + * @run main/othervm KeepAliveTest 48 + * @run main/othervm KeepAliveTest 49 + * @run main/othervm KeepAliveTest 50 + * @run main/othervm KeepAliveTest 51 + * @run main/othervm KeepAliveTest 52 + * @run main/othervm KeepAliveTest 53 + * @run main/othervm KeepAliveTest 54 + * @run main/othervm KeepAliveTest 55 + * @run main/othervm KeepAliveTest 56 + * @run main/othervm KeepAliveTest 57 + * @run main/othervm KeepAliveTest 58 + * @run main/othervm KeepAliveTest 59 + * @run main/othervm KeepAliveTest 60 + * @run main/othervm KeepAliveTest 61 + * @run main/othervm KeepAliveTest 62 + * @run main/othervm KeepAliveTest 63 + * @run main/othervm KeepAliveTest 64 + * @run main/othervm KeepAliveTest 65 + * @run main/othervm KeepAliveTest 66 + * @run main/othervm KeepAliveTest 67 + * @run main/othervm KeepAliveTest 68 + * @run main/othervm KeepAliveTest 69 + * @run main/othervm KeepAliveTest 70 + * @run main/othervm KeepAliveTest 71 + * @run main/othervm KeepAliveTest 72 + * @run main/othervm KeepAliveTest 73 + * @run main/othervm KeepAliveTest 74 + * @run main/othervm KeepAliveTest 75 + * @run main/othervm KeepAliveTest 76 + * @run main/othervm KeepAliveTest 77 + * @run main/othervm KeepAliveTest 78 + * @run main/othervm KeepAliveTest 79 + * @run main/othervm KeepAliveTest 80 + * @run main/othervm KeepAliveTest 81 + * @run main/othervm KeepAliveTest 82 + * @run main/othervm KeepAliveTest 83 + * @run main/othervm KeepAliveTest 84 + * @run main/othervm KeepAliveTest 85 + * @run main/othervm KeepAliveTest 86 + * @run main/othervm KeepAliveTest 87 + * @run main/othervm KeepAliveTest 88 + * @run main/othervm KeepAliveTest 89 + * @run main/othervm KeepAliveTest 90 + * @run main/othervm KeepAliveTest 91 + * @run main/othervm KeepAliveTest 92 + * @run main/othervm KeepAliveTest 93 + * @run main/othervm KeepAliveTest 94 + * @run main/othervm KeepAliveTest 95 + * @run main/othervm KeepAliveTest 96 + * @run main/othervm KeepAliveTest 97 + * @run main/othervm KeepAliveTest 98 + * @run main/othervm KeepAliveTest 99 + * @run main/othervm KeepAliveTest 100 + * @run main/othervm KeepAliveTest 101 + * @run main/othervm KeepAliveTest 102 + * @run main/othervm KeepAliveTest 103 + * @run main/othervm KeepAliveTest 104 + * @run main/othervm KeepAliveTest 105 + * @run main/othervm KeepAliveTest 106 + * @run main/othervm KeepAliveTest 107 + * @run main/othervm KeepAliveTest 108 + * @run main/othervm KeepAliveTest 109 + * @run main/othervm KeepAliveTest 110 + * @run main/othervm KeepAliveTest 111 + * @run main/othervm KeepAliveTest 112 + * @run main/othervm KeepAliveTest 113 + * @run main/othervm KeepAliveTest 114 + * @run main/othervm KeepAliveTest 115 + * @run main/othervm KeepAliveTest 116 + * @run main/othervm KeepAliveTest 117 + * @run main/othervm KeepAliveTest 118 + * @run main/othervm KeepAliveTest 119 + * @run main/othervm KeepAliveTest 120 + * @run main/othervm KeepAliveTest 121 + * @run main/othervm KeepAliveTest 122 + * @run main/othervm KeepAliveTest 123 + * @run main/othervm KeepAliveTest 124 + * @run main/othervm KeepAliveTest 125 + * @run main/othervm KeepAliveTest 126 + * @run main/othervm KeepAliveTest 127 + * @run main/othervm KeepAliveTest 128 + * @run main/othervm KeepAliveTest 129 + * @run main/othervm KeepAliveTest 130 + * @run main/othervm KeepAliveTest 131 + * @run main/othervm KeepAliveTest 132 + * @run main/othervm KeepAliveTest 133 + * @run main/othervm KeepAliveTest 134 + * @run main/othervm KeepAliveTest 135 + * @run main/othervm KeepAliveTest 136 + * @run main/othervm KeepAliveTest 137 + * @run main/othervm KeepAliveTest 138 + * @run main/othervm KeepAliveTest 139 + * @run main/othervm KeepAliveTest 140 + * @run main/othervm KeepAliveTest 141 + * @run main/othervm KeepAliveTest 142 + * @run main/othervm KeepAliveTest 143 + * @run main/othervm KeepAliveTest 144 + * @run main/othervm KeepAliveTest 145 + * @run main/othervm KeepAliveTest 146 + * @run main/othervm KeepAliveTest 147 + * @run main/othervm KeepAliveTest 148 + * @run main/othervm KeepAliveTest 149 + * @run main/othervm KeepAliveTest 150 + * @run main/othervm KeepAliveTest 151 + * @run main/othervm KeepAliveTest 152 + * @run main/othervm KeepAliveTest 153 + * @run main/othervm KeepAliveTest 154 + * @run main/othervm KeepAliveTest 155 + * @run main/othervm KeepAliveTest 156 + * @run main/othervm KeepAliveTest 157 + * @run main/othervm KeepAliveTest 158 + * @run main/othervm KeepAliveTest 159 + */ + +import java.nio.charset.StandardCharsets; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Proxy.Type; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.CountDownLatch; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import sun.net.www.http.HttpClient; +import sun.net.www.http.KeepAliveCache; +import sun.net.www.protocol.http.HttpURLConnection; +import jdk.test.lib.net.URIBuilder; + +public class KeepAliveTest { + private static final Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); + private static final String NOT_CACHED = "NotCached"; + private static final String CLIENT_SEPARATOR = ";"; + private static final String NEW_LINE = "\r\n"; + private volatile int SERVER_PORT = 0; + /* + * isProxySet is shared variable between server thread and client thread(main) and it should be set and reset to false for each and + * every scenario. + * isProxySet variable should be set by server thread before proceeding to client thread(main). + */ + private volatile boolean isProxySet = false; + private static final String CONNECTION_KEEP_ALIVE_ONLY = "Connection: keep-alive"; + private static final String PROXY_CONNECTION_KEEP_ALIVE_ONLY = "Proxy-Connection: keep-alive"; + private static final String KEEP_ALIVE_TIMEOUT_NEG = "Keep-alive: timeout=-20"; + private static final String KEEP_ALIVE_TIMEOUT_ZERO = "Keep-alive: timeout=0"; + private static final String KEEP_ALIVE_TIMEOUT = "Keep-alive: timeout=20"; + private static final String KEEP_ALIVE_PROXY_TIMEOUT = "Keep-alive: timeout=120"; + private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_NEGATIVE = "http.keepAlive.time.server=-100"; + private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_NEGATIVE = "http.keepAlive.time.proxy=-200"; + private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_ZERO = "http.keepAlive.time.server=0"; + private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_ZERO = "http.keepAlive.time.proxy=0"; + private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_POSITIVE = "http.keepAlive.time.server=100"; + private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_POSITIVE = "http.keepAlive.time.proxy=200"; + private static final String CONNECTION_KEEP_ALIVE_WITH_TIMEOUT = CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + + KEEP_ALIVE_TIMEOUT; + /* + * Following Constants represents Client Side Properties and is used as reference in below table as + * CLIENT_INPUT_CONSTANT_NAMES + */ + private static final String SERVER_100_NEGATIVE = CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_NEGATIVE; + private static final String PROXY_200_NEGATIVE = CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_NEGATIVE; + private static final String SERVER_ZERO = CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_ZERO; + private static final String PROXY_ZERO = CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_ZERO; + private static final String SERVER_100 = CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_POSITIVE; + private static final String PROXY_200 = CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_POSITIVE; + + /* + * CONSTANTS A,B,C,D,E,NI,F,G,H,I represents ServerScenarios and is used as reference in below table + * as SERVER_RESPONSE_CONSTANT_NAME + */ + private static final String A = CONNECTION_KEEP_ALIVE_ONLY; + private static final String B = CONNECTION_KEEP_ALIVE_WITH_TIMEOUT; + private static final String C = PROXY_CONNECTION_KEEP_ALIVE_ONLY; + private static final String D = PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + CONNECTION_KEEP_ALIVE_ONLY; + private static final String E = C + NEW_LINE + KEEP_ALIVE_PROXY_TIMEOUT; + private static final String NI = "NO_INPUT"; + private static final String F = A + NEW_LINE + KEEP_ALIVE_TIMEOUT_NEG; + private static final String G = A + NEW_LINE + KEEP_ALIVE_TIMEOUT_ZERO; + private static final String H = C + NEW_LINE + KEEP_ALIVE_TIMEOUT_NEG; + private static final String I = C + NEW_LINE + KEEP_ALIVE_TIMEOUT_ZERO; + + /* + * There are 160 scenarios run by this program. + * For every scenario there is mapping between serverScenarios[int],clientScenarios[int] and expectedOutput[int] + * + * serverScenarios[0] clientScenarios[0] expectedOutput[0] + * serverScenarios[1] clientScenarios[1] expectedOutput[1] + * serverScenarios[2] clientScenarios[2] expectedOutput[2] + * + * ... + * + * serverScenarios[159] cientScenarios[159] expectedOutput[159] + * + * whereas serverScenarios[int] is retrieved using getServerScenario(int) + * whereas clientScenarios[int] is retrieved using clientScenario[getClientScenarioNumber[int]] + * and + * expectedOutput[int] is retrieved using expectedOuput[int] directly. + * + */ + + /* Here is the complete table of server_response, client system properties input and expected cached timeout at client side */ + /* ScNo | SERVER RESPONSE (SERVER_RESPONSE_CONSTANT_NAME)| CLIENT SYSTEM PROPERTIES INPUT (CLIENT_INPUT_CONSTANT_NAMES) | EXPECTED CACHED TIMEOUT AT CLIENT SIDE + ***************************************************************************************************************************************** + * 0 | Connection: keep-alive (A) | No Input Provided (NI) | Default Timeout set to 5 + *--------------------------------------------------------------------------------------------------------------------------- + * 1 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 (SERVER_100)| Client Timeout set to 100 + *-------------------------------------------------------------------------------------------------------------------------- + * 2 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.proxy=200 (PROXY_200) | Default Timeout set to 5 + *--------------------------------------------------------------------------------------------------------------------------- + * 3 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 100 + * | | (SERVER_100 && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 4 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 | Default Timeout set to 5 + * | | (SERVER_100_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 5 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.proxy=-200 | Default Timeout set to 5 + * | | (PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 6 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Default Timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 7 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 | Connection Closed Immediately + * | | (SERVER_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 8 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.proxy=0 | Default Timeout set to 5 + * | | (PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 9 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Connection Closed Immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 10 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Connection Closed Immediately + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 11 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Default Timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 12 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 100 + * | | (SERVER_100 && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 13 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Connection Closed Immediately + * | | (SERVER_ZERO && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 14 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 100 + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 15 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Default Timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 16 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | No Input Provided (NI) | Timeout set to 20 + *------------------------------------------------------------------------------------------------------------------------ + * 17 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 | Timeout set to 20 + * | | (SERVER_100) | + *--------------------------------------------------------------------------------------------------------------------------- + * 18 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 + * | | (PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 19 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 + * | | (SERVER_100 && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 20 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=-100 | Timeout set to 20 + * | | (SERVER_100_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 21 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 + * | | (PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 22 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| + *--------------------------------------------------------------------------------------------------------------------------- + * 23 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 | Timeout set to 20 + * | | (SERVER_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 24 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 + * | | (PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 25 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 + * | | (SERVER_ZERO && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 26 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 27 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 28 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 + * | | (SERVER_100 && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 29 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 + * | | (SERVER_ZERO && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 30 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 31 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 32 |Proxy-Connection: keep-alive (C) | No Input Provided (NI) | Default timeout set to 60 + *--------------------------------------------------------------------------------------------------------------------------- + * 33 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=100 | Default timeout set to 60 + * | | (SERVER_100) | + *--------------------------------------------------------------------------------------------------------------------------- + * 34 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------- + * 35 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_100 && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------- + * 36 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=-100 | Default timeout set to 60 + * | | (SERVER_100_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 37 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | | (PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 38 |Proxy-Connection: keep-alive (C) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | |(SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| + *--------------------------------------------------------------------------------------------------------------------------- + * 39 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 | Default timeout set to 60 + * | | (SERVER_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 40 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 41 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 42 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------------- + * 43 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------------- + * 44 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100 && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 45 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_ZERO && PROXY_200) | + *--------------------------------------------------------------------------------------------------------------------------- + * 46 |Proxy-Connection: keep-alive (C) |-Dhttp.keepAlive.time.server=100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------- + * 47 |Proxy-Connection: keep-alive (C) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------- + * 48 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | No Input Provided (NI) | Default timeout set to 60 + *----------------------------------------------------------------------------------------------------------------------------- + * 49 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 | Default timeout set to 60 + * | | (SERVER_100) | + *--------------------------------------------------------------------------------------------------------------------------- + * 50 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------ + * 51 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_100 && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------ + * 52 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100 | Default timeout set to 60 + * | | (SERVER_100_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------ + * 53 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | | (PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------ + * 54 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100&& | + * | | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE | + *------------------------------------------------------------------------------------------------------------------------------- + * 55 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 | Default timeout set to 60 + * | | (SERVER_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 56 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 57 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 58 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 59 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 60 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100 && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 61 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_ZERO && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------ + * 62 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------ + * 63 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------- + * 64 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| No Input Provided (NI) | Timeout set to 120 + *------------------------------------------------------------------------------------------------------------------------------- + * 65 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 | Timeout set to 120 + * | | (SERVER_100) | + *------------------------------------------------------------------------------------------------------------------------------- + * 66 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 + * | | (PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------- + * 67 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 + * | | (SERVER_100 && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------- + * 68 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 | Timeout set to 120 + * | | (SERVER_100_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------- + * 69 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 + * | | (PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------- + * 70 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| + *------------------------------------------------------------------------------------------------------------------------------- + * 71 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 | Timeout set to 120 + * | | (SERVER_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------- + * 72 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 + * | | (PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------- + * 73 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 + * | | (SERVER_ZERO && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------- + * 74 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------- + * 75 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------- + * 76 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 + * | | (SERVER_100 && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------- + * 77 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 + * | | (SERVER_ZERO && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------- + * 78 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------- + * 79 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *----------------------------------------------------------------------------------------------------------------------------- + * 80 |No Input (NI) | No Input Provided (NI) | default timeout set to 5 + *----------------------------------------------------------------------------------------------------------------------------- + * 81 |No Input (NI) | -Dhttp.keepAlive.time.server=100 | Timeout set to 100 + * | | (SERVER_100) | + *----------------------------------------------------------------------------------------------------------------------------- + * 82 |No Input (NI) | -Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 + * | | (PROXY_200) | + *----------------------------------------------------------------------------------------------------------------------------- + * 83 |No Input (NI) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | client timeot set to 100 + * | | (SERVER_100 && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------ + * 84 |No Input (NI) | -Dhttp.keepAlive.time.server=-100 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------ + * 85 |No Input (NI) | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 + * | | (PROXY_200_NEGATIVE) | + *---------------------------------------------------------------------------------------------------------------------------- + * 86 |No Input (NI) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| + *------------------------------------------------------------------------------------------------------------------------------ + * 87 |No Input (NI) | -Dhttp.keepAlive.time.server=0 | close connection immediately + * | | (SERVER_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------------- + * 88 |No Input (NI) | -Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 + * | | (PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------------- + * 89 |No Input (NI) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------------- + * 90 |No Input (NI) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 91 |No Input (NI) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 92 |No Input (NI) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 100 + * | | (SERVER_100 && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 93 |No Input (NI) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 94 |No Input (NI) |-Dhttp.keepAlive.time.server=100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | Timeout set to 100 + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 95 |No Input (NI) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 96 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) | No Input Provided (NI) | default timeout set to 5 + *-------------------------------------------------------------------------------------------------------------------------------- + * 97 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 | Timeout set to 100 + * | | (SERVER_100) | + *-------------------------------------------------------------------------------------------------------------------------------- + * 98 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 + * | | (PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 99 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 && | + * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 100 + * | |(SERVER_100 && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 100 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 | default timeout set to 5 + * | |(SERVER_100_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 101 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 + * | |(PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 102 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| + *------------------------------------------------------------------------------------------------------------------------------------- + * 103 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 | close connection immediately + * | | (SERVER_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 104 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 + * | | (PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 105 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 106 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO_NEGATIVE)| + *------------------------------------------------------------------------------------------------------------------------------------- + * 107 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 108 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 && | + * | |-Dhttp.keepAlive.time.proxy=0 | Timeout set to 100 + * | | (SERVER_100 && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 109 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 && | + * | |-Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 110 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | Timeout set to 100 + * | |(SERVER_100 && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 111 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 112 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | No Input Provided (NI) | close connection immediately + *------------------------------------------------------------------------------------------------------------------------------------- + * 113 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 | close connection immediately + * | | (SERVER_100) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 114 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 115 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_100 && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 116 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=-100 | close connection immediately + * | | (SERVER_100_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------ + * 117 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 118 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) |-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 119 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 | close connection immediately + * | | (SERVER_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 120 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------ + * 121 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 122 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 123 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 124 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100 && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 125 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 126 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 127 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=-100 &&| + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 128 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| No Input Provided (NI) | default timeout set to 60 + --------------------------------------------------------------------------------------------------------------------------------------- + * 129 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=100 | default timeout set to 60 + * | | (SERVER_100) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 130 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 131 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_100 && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 132 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=-100 | default timeout set to 60 + * | | (SERVER_100_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 133 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 + * | | (PROXY_200_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 134 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)|-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| + *--------------------------------------------------------------------------------------------------------------------------------- + * 135 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 | default timeout set to 60 + * | | (SERVER_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 136 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (PROXY_ZERO) | + *---------------------------------------------------------------------------------------------------------------------------------- + * 137 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 138 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *--------------------------------------------------------------------------------------------------------------------------------------- + * 139 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 140 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100 && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 141 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 + * | | (SERVER_ZERO && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 142 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)|-Dhttp.keepAlive.time.server=100 && | + * | |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 143 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)|-Dhttp.keepAlive.time.server=-100 && | + * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 144 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | No Input Provided (NI) | close connection immediately + *-------------------------------------------------------------------------------------------------------------------------------------- + * 145 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 | close connection immediately + * | | (SERVER_100) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 146 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 147 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_100 && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 148 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 | close connection immediately + * | | (SERVER_100_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 149 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 150 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | + *------------------------------------------------------------------------------------------------------------------------------------ + * 151 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 | close connection immediately + * | | (SERVER_ZERO) | + *----------------------------------------------------------------------------------------------------------------------------------- + * 152 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (PROXY_ZERO) | + *--------------------------------------------------------------------------------------------------------------------------------- + * 153 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_ZERO && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------ + * 154 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 155 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | + *------------------------------------------------------------------------------------------------------------------------------------- + * 156 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately + * | | (SERVER_100 && PROXY_ZERO) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 157 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 && | + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_ZERO && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 158 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 && | + * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately + * | | (SERVER_100 && PROXY_200_NEGATIVE) | + *-------------------------------------------------------------------------------------------------------------------------------------- + * 159 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 && | + * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately + * | | (SERVER_100_NEGATIVE && PROXY_200) | + *-------------------------------------------------------------------------------------------------------------------------------------- + */ + + /* private static final String[] serverScenarios = { + A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, + B, B, B, B, B, B, B, B, B, B,B, B, B, B, B, B, + C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, + D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, + E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, + NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, + G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, + H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I + }; */ + /* + * following are client scenarios which are repeated. + */ + private static final String[] a = { + NI, SERVER_100, PROXY_200, SERVER_100 + CLIENT_SEPARATOR + PROXY_200, SERVER_100_NEGATIVE, + PROXY_200_NEGATIVE, SERVER_100_NEGATIVE + CLIENT_SEPARATOR + PROXY_200_NEGATIVE, + SERVER_ZERO, PROXY_ZERO, SERVER_ZERO + CLIENT_SEPARATOR + PROXY_ZERO, + SERVER_ZERO + CLIENT_SEPARATOR + PROXY_200_NEGATIVE, SERVER_100_NEGATIVE + CLIENT_SEPARATOR + PROXY_ZERO, + SERVER_100 + CLIENT_SEPARATOR + PROXY_ZERO, SERVER_ZERO + CLIENT_SEPARATOR + PROXY_200, + SERVER_100 + CLIENT_SEPARATOR + PROXY_200_NEGATIVE, SERVER_100_NEGATIVE + CLIENT_SEPARATOR + PROXY_200 + }; + + /* private String[] clientScenarios = { + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], + }; */ + + private static final String[] clientScenarios = { + a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15] + }; + + private static final int[] expectedValues = { + 5, 100, 5, 100, 5, 5, 5, 0, 5, 0, 0, 5, 100, 0, 100, 5, + 20, 20 , 20, 20, 20, 20, 20, 20, 20, 20 , 20, 20, 20, 20, 20, 20, + 60, 60, 200, 200, 60, 60, 60, 60, 0, 0, 60, 0, 0, 200, 60, 200, + 60, 60, 200, 200, 60, 60, 60, 60, 0, 0, 60, 0, 0, 200, 60, 200, + 120, 120, 120, 120,120,120,120,120,120, 120, 120, 120, 120, 120, 120, 120, + 5, 100, 5, 100, 5, 5, 5, 0, 5, 0, 0, 5, 100, 0, 100, 5, + 5, 100, 5, 100, 5, 5, 5, 0, 5, 0, 0, 5, 100, 0, 100, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 60, 200, 200, 60, 60, 60, 60, 0, 0, 60, 0, 0, 200, 60, 200, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + private final CountDownLatch countDownLatch = new CountDownLatch(1); + + private final CountDownLatch serverCountDownLatch = new CountDownLatch(1); + + /* + * setting of client properties -Dhttp.keepAlive.time.server and -Dhttp.keepAlive.time.proxy is handled through this method. + * There are 16 client scenarios in total starting with scenarioNumber 0(zero) and ending with 15. + * Server Scenarios are grouped into batch of 16 scenarios. + * There are 10 batches in total and each batch contains 16 scenarios so 10 * 16 = 160 scenarios in total. + * 16 Client Scenarios are used repeatedly for every server scenario batch. + * for serverscenario[0],serverscenario[16],serverscenario[32] ... serverscenario[144] is mapped to clientscenario[0] + * for serverscenario[1],serverscenario[17],serverscenario[33] ... serverscenario[145] is mapped to clientscenario[1] + * for serverscenario[2],serverscenario[18],serverscenario[34] ... serverscenario[146] is mapped to clientscenario[2] + * ... + * for serverscenario[15],serverscenario[31],serverscenario[47] ... serverscenario[159] is mapped to clientscenario[15] + */ + private int getClientScenarioNumber(int scenarioNumber) { + return scenarioNumber % 16 ; + } + + /* + * Returns SERVER_RESPONSE as String based on integer inputParameter scenarioNumber. + * Server Scenarios are grouped into batch of 16 scenarios starting with scenarioNumber 0 (zero) + * so there are 10 batches in total and each batch contains 16 scenarios so 10 * 16 = 160 scenarios in total. + * For each batch of 16 scenarios, there will be common SERVER_RESPONSE for all 16 scenarios in batch. + * for scenario numbers from 0 to 15 server response is: Connection:keep-alive + * for scenario numbers from 16 to 31 server response is: SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=20 + * for scenario numbers from 32 to 47 server response is: SERVER_RESPONSE=Proxy-Connection: keep-alive + * for scenario numbers from 48 to 63 server response is: SERVER_RESPONSE=Connection:keep-alive\r\nProxy-connection:keep-alive + * for scenario numbers from 64 to 79 server response is: SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 + * for scenario numbers from 80 to 95 server response is: SERVER_RESPONSE=No Input + * for scenario numbers from 96 to 111 server response is: SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=-20 + * for scenario numbers from 112 to 127 server resonse is: Connection: keep-alive\r\nKeep-alive: timeout=0 + * for scenario numbers from 128 to 143 server response is: Proxy-connection:keep-alive\r\nKeep-alive:timeout=-20 + * for scenario numbers from 144 to 159 server response is: Proxy-connection:keep-alive\r\nKeep-alive:timeout=0 + */ + private String getServerScenario(int scenarioNumber) { + /* + * ServerResponse for scenarios from 0 to 15 + * SERVER_RESPONSE:Connection:keep-alive + */ + if(scenarioNumber >= 0 && scenarioNumber <= 15) { + return A; + } + /* + * ServerResponse for scenarios from 16 to 31 + * SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=20 + */ + else if (scenarioNumber >= 16 && scenarioNumber <= 31){ + return B; + } + /* + * ServerResponse for scenarios from 32 to 47 + * SERVER_RESPONSE=Proxy-Connection: keep-alive + */ + else if (scenarioNumber >= 32 && scenarioNumber <= 47){ + return C; + } + /* + * ServerResponse for scenarios from 48 to 63 + * SERVER_RESPONSE=Connection:keep-alive\r\nProxy-connection:keep-alive + */ + else if (scenarioNumber >= 48 && scenarioNumber <= 63){ + return D; + /* + * ServerResponse for scenarios from 64 to 79 + * SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 + */ + } else if (scenarioNumber >= 64 && scenarioNumber <= 79){ + return E; + } + /* + * ServerResponse for scenarios from 80 to 95 + * SERVER_RESPONSE=No Input + */ + else if (scenarioNumber >= 80 && scenarioNumber <= 95){ + return NI; + } + /* + * ServerResponse for scenarios from 96 to 111 + * SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=-20 + */ + else if (scenarioNumber >= 96 && scenarioNumber <= 111){ + return F; + } + /* + * ServerResponse for scenarios from 112 to 127 + * SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=0 + */ + else if (scenarioNumber >= 112 && scenarioNumber <= 127){ + return G; + } + /* + * ServerResponse for scenarios from 128 to 143 + * SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=-20 + */ + else if (scenarioNumber >= 128 && scenarioNumber <= 143){ + return H; + } + /* + * ServerResponse for scenarios from 144 to 159 + * SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=0 + */ + else if (scenarioNumber >= 144 && scenarioNumber <= 159){ + return I; + } + /*Invalid Case*/ + return null; + } + + private void startScenario(int scenarioNumber) throws Exception { + //test scenarios are skipped because of JDK-8291638 + if((scenarioNumber >= 112 && scenarioNumber <= 127) || (scenarioNumber >= 144 && scenarioNumber <= 159)) { + System.out.println("Scenario Skipped:"+scenarioNumber); + this.countDownLatch.countDown(); + return; + } + System.out.println("serverScenarios[" + scenarioNumber + "]=" + getServerScenario(scenarioNumber)); + System.out.println("clientScenarios[" + scenarioNumber + "]=" + clientScenarios[getClientScenarioNumber(scenarioNumber)]); + if(expectedValues[scenarioNumber] == 0) { + System.out.println("ExpectedOutput=" + NOT_CACHED); + } else { + System.out.println("ExpectedOutput=" + expectedValues[scenarioNumber]); + } + System.out.println(); + startServer(scenarioNumber); + runClient(scenarioNumber); + } + + private void startServer(int scenarioNumber) { + Thread server = new Thread(new Runnable() { + @Override + public void run() { + try { + executeServer(scenarioNumber); + } catch (IOException e) { + e.printStackTrace(); + } + } + }, "SERVER"); + server.start(); + } + + private void readAll(Socket s) throws IOException { + byte[] buf = new byte[128]; + int c; + String request = ""; + InputStream is = s.getInputStream(); + while ((c = is.read(buf)) > 0) { + request += new String(buf, 0, c, StandardCharsets.US_ASCII); + if (request.contains("\r\n\r\n")) { + return; + } + } + if (c == -1) { + throw new IOException("Socket closed"); + } + } + + private void executeServer(int scenarioNumber) throws IOException { + String serverScenarioContent = null; + if (!getServerScenario(scenarioNumber).equalsIgnoreCase(NI)) { + serverScenarioContent = getServerScenario(scenarioNumber) + NEW_LINE; + /* + * isProxySet should be set before Server is moved to Listen State. + */ + if (serverScenarioContent.contains("Proxy")) { + isProxySet = true; + } else { + isProxySet = false; + } + } + ServerSocket serverSocket = null; + Socket socket = null; + OutputStreamWriter out = null; + InetAddress loopback = InetAddress.getLoopbackAddress(); + try { + serverSocket = new ServerSocket(); + serverSocket.bind(new InetSocketAddress(loopback, 0)); + SERVER_PORT = serverSocket.getLocalPort(); + //serverReady = true; + this.serverCountDownLatch.countDown(); + System.out + .println("SERVER_PORT= " + SERVER_PORT +" isProxySet=" + isProxySet); + /* + * Server will be waiting for clients to connect. + */ + socket = serverSocket.accept(); + readAll(socket); + out = new OutputStreamWriter(socket.getOutputStream()); + String BODY = "SERVER REPLY: Hello world"; + String CLEN = "Content-Length: " + BODY.length() + NEW_LINE; + /* send the header */ + out.write("HTTP/1.1 200 OK\r\n"); + out.write("Content-Type: text/plain; charset=iso-8859-1\r\n"); + /* + * append each scenario content from array. + */ + if(serverScenarioContent != null) { + out.write(serverScenarioContent); + } + out.write(CLEN); + out.write(NEW_LINE); + out.write(BODY); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + out.flush(); + out.close(); + } + if (socket != null) { + socket.close(); + } + if (serverSocket != null) { + serverSocket.close(); + } + } + } + + private void runClient(int scenarioNumber) throws Exception { + try { + connectToServerURL(scenarioNumber); + } finally { + System.out.println("client count down latch:" + scenarioNumber); + this.countDownLatch.countDown(); + System.out.println(); + System.out.println(); + } + } + + private void connectToServerURL(int scenarioNumber) throws Exception { + // System.setProperty("java.net.useSystemProxies", "false"); + // System.setProperty("http.nonProxyHosts", ""); + // System.setProperty("http.proxyHost", "localhost"); + // System.setProperty("http.proxyPort", String.valueOf(SERVER_PORT)); + System.out.println("Following are Existing System Properties if set any"); + System.out.println("http.keepAlive.time.server:" + System.getProperty("http.keepAlive.time.server")); + System.out.println("http.keepAlive.time.proxy:" + System.getProperty("http.keepAlive.time.proxy")); + System.setProperty("java.net.useSystemProxies", "false"); + System.out.println("http.proxyPort:"+System.getProperty("http.proxyPort")); + System.out.println("http.proxyHost:"+System.getProperty("http.proxyHost")); + System.clearProperty("http.keepAlive.time.server"); + System.clearProperty("http.keepAlive.time.proxy"); + // fetch clientScenearios for each scenarioNumber from array and set it to + // System property. + if (!clientScenarios[getClientScenarioNumber(scenarioNumber)].equalsIgnoreCase(NI)) { + System.out.println("Client Input Parsing"); + for (String clientScenarioString : clientScenarios[getClientScenarioNumber(scenarioNumber)].split(CLIENT_SEPARATOR)) { + System.out.println(clientScenarioString); + String key = clientScenarioString.split("=")[0]; + String value = clientScenarioString.split("=")[1]; + System.setProperty(key, value); + } + } + // wait until ServerSocket moves to listening state. + this.serverCountDownLatch.await(); + System.out.println("client started"); + URL url = URIBuilder.newBuilder().scheme("http").loopback().port(SERVER_PORT).toURL(); + System.out.println("connecting from client to SERVER URL:" + url); + HttpURLConnection httpUrlConnection = null; + /* + * isProxySet is set to true when Expected Server Response contains Proxy-Connection header. + */ + if (isProxySet) { + httpUrlConnection = (sun.net.www.protocol.http.HttpURLConnection) url + .openConnection(new Proxy(Type.HTTP, new InetSocketAddress("localhost", SERVER_PORT))); + } else { + httpUrlConnection = (sun.net.www.protocol.http.HttpURLConnection) url.openConnection(); + } + InputStreamReader inputStreamReader = new InputStreamReader(httpUrlConnection.getInputStream()); + BufferedReader bufferedReader = null; + try { + bufferedReader = new BufferedReader(inputStreamReader); + while (true) { + String eachLine = bufferedReader.readLine(); + if (eachLine == null) { + break; + } + System.out.println(eachLine); + } + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + // System.out.println("ResponseCode:" + httpUrlConnection.getResponseCode()); + // System.out.println("ResponseMessage:" + httpUrlConnection.getResponseMessage()); + // System.out.println("Content:" + httpUrlConnection.getContent()); + // Thread.sleep(2000); + for (Entry> header : httpUrlConnection.getHeaderFields().entrySet()) { + System.out.println(header.getKey() + "=" + header.getValue()); + } + fetchInfo(scenarioNumber, httpUrlConnection); + } + + private void fetchInfo(int scenarioNumber, sun.net.www.protocol.http.HttpURLConnection httpUrlConnection) + throws Exception { + Field field = Class.forName("sun.net.www.protocol.http.HttpURLConnection").getDeclaredField("http"); + field.setAccessible(true); + HttpClient httpClient = (HttpClient) field.get(httpUrlConnection); + // System.out.println("httpclient=" + httpClient); + Field keepAliveField = Class.forName("sun.net.www.http.HttpClient").getDeclaredField("kac"); + keepAliveField.setAccessible(true); + KeepAliveCache keepAliveCache = (KeepAliveCache) keepAliveField.get(httpClient); + System.out.println("keepAliveCache" + keepAliveCache); + System.out.println("SERVER URL:" + httpUrlConnection.getURL()); + /* + * create KeepAliveKey(URL,Object) object and compare created KeepAliveKey and + * existing using equals() method: KeepAliveKey.equals() + */ + Class keepAliveKeyClass = Class.forName("sun.net.www.http.KeepAliveKey"); + // System.out.println("keepAliveKeyClass=" + keepAliveKeyClass); + Constructor keepAliveKeyClassconstructor = keepAliveKeyClass.getDeclaredConstructors()[0]; + keepAliveKeyClassconstructor.setAccessible(true); + Object expectedKeepAliveKey = keepAliveKeyClassconstructor.newInstance(httpUrlConnection.getURL(), null); + System.out.println("ExpectedKeepAliveKey=" + expectedKeepAliveKey); + Object clientVectorObjectInMap = keepAliveCache.get(expectedKeepAliveKey); + System.out.println("ClientVector=" + clientVectorObjectInMap); + HttpClient httpClientCached = keepAliveCache.get(httpUrlConnection.getURL(), null); + System.out.println("HttpClient in Cache:" + httpClientCached); + if(httpClientCached != null) { + System.out.println("KeepingAlive:" + httpClientCached.isKeepingAlive()); + System.out.println("UsingProxy:" + httpClientCached.getUsingProxy()); + System.out.println("ProxiedHost:" + httpClientCached.getProxyHostUsed()); + System.out.println("ProxiedPort:" + httpClientCached.getProxyPortUsed()); + System.out.println("ProxyPortUsingSystemProperty:" + System.getProperty("http.proxyPort")); + System.out.println("ProxyHostUsingSystemProperty:" + System.getProperty("http.proxyHost")); + System.out.println("http.keepAlive.time.server=" + System.getProperty("http.keepAlive.time.server")); + System.out.println("http.keepAlive.time.proxy=" + System.getProperty("http.keepAlive.time.proxy")); + Class clientVectorClass = Class.forName("sun.net.www.http.ClientVector"); + // System.out.println("clientVectorClass=" + clientVectorClass); + Field napField = clientVectorClass.getDeclaredField("nap"); + napField.setAccessible(true); + int napValue = (int) napField.get(clientVectorObjectInMap); + int actualValue = napValue / 1000; + // System.out.println("nap=" + napValue / 1000); + System.out.printf("ExpectedOutput:%d ActualOutput:%d ", expectedValues[scenarioNumber], actualValue); + System.out.println(); + if (expectedValues[scenarioNumber] != actualValue) { + throw new RuntimeException( + "ExpectedOutput:" + expectedValues[scenarioNumber] + " ActualOutput: " + actualValue); + } + } else { + //executed when value is not cached. + String expected = expectedValues[scenarioNumber] == 0 ? NOT_CACHED + : String.valueOf(expectedValues[scenarioNumber]); + System.out.println("ExpectedOutput:" + expected + " ActualOutput:" + NOT_CACHED); + if (!expected.equalsIgnoreCase(NOT_CACHED)) { + throw new RuntimeException("ExpectedOutput:" + expected + " ActualOutput:" + NOT_CACHED); + } + } + } + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + throw new IllegalArgumentException("Usage:java KeepAliveTest.java "); + } + logger.setLevel(Level.FINEST); + ConsoleHandler h = new ConsoleHandler(); + h.setLevel(Level.FINEST); + logger.addHandler(h); + KeepAliveTest keepAliveTest = new KeepAliveTest(); + if (args.length != 0) { + keepAliveTest.startScenario(Integer.valueOf(args[0])); + } + // make main thread wait until server and client is completed. + keepAliveTest.countDownLatch.await(); + } +} From 0476345ce007d26a9d3dffe785e97e5d123345f1 Mon Sep 17 00:00:00 2001 From: Dhamoder Nalla Date: Tue, 9 Apr 2024 18:04:23 +0100 Subject: [PATCH 8/8] Fix white spaces --- .../sun/net/www/http/KeepAliveCache.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java index 99160813ebb..b93653e70e2 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -129,11 +129,11 @@ public void put(final URL url, Object obj, HttpClient http) { if (startThread) { clear(); /* Unfortunately, we can't always believe the keep-alive timeout we got - * back from the server. If I'm connected through a Netscape proxy - * to a server that sent me a keep-alive - * time of 15 sec, the proxy unilaterally terminates my connection - * The robustness to get around this is in HttpClient.parseHTTP() - */ + * back from the server. If I'm connected through a Netscape proxy + * to a server that sent me a keep-alive + * time of 15 sec, the proxy unilaterally terminates my connection + * The robustness to get around this is in HttpClient.parseHTTP() + */ final KeepAliveCache cache = this; AccessController.doPrivileged(new PrivilegedAction() { public Void run() { @@ -154,14 +154,14 @@ public Void run() { keepAliveTimer.start(); return null; } - }); + }); } KeepAliveKey key = new KeepAliveKey(url, obj); ClientVector v = super.get(key); - if (v == null) { - int keepAliveTimeout = http.getKeepAliveTimeout(); + if (v == null) { + int keepAliveTimeout = http.getKeepAliveTimeout(); if (keepAliveTimeout == 0) { keepAliveTimeout = getUserKeepAlive(http.getUsingProxy()); if (keepAliveTimeout == -1) { @@ -187,10 +187,10 @@ public Void run() { v.put(http); super.put(key, v); } - } else { + } else { oldClient = v.put(http); + } } - } // close after releasing locks if (oldClient != null) { oldClient.closeServer(); @@ -225,7 +225,6 @@ synchronized void removeVector(KeepAliveKey k) { * Check to see if this URL has a cached HttpClient */ public synchronized HttpClient get(URL url, Object obj) { - KeepAliveKey key = new KeepAliveKey(url, obj); ClientVector v = super.get(key); if (v == null) { // nothing in cache yet @@ -280,10 +279,10 @@ public void run() { } // close connections outside cacheLock if (closeList != null) { - for (HttpClient hc : closeList) { - hc.closeServer(); - } - } + for (HttpClient hc : closeList) { + hc.closeServer(); + } + } } while (!isEmpty()); } @@ -328,7 +327,7 @@ synchronized HttpClient get() { pollFirst(); if (KeepAliveCache.logger.isLoggable(PlatformLogger.Level.FINEST)) { String msg = "cached HttpClient was idle for " - + Long.toString(currentTime - e.idleStartTime); + + Long.toString(currentTime - e.idleStartTime); KeepAliveCache.logger.finest(msg); } return e.hc; @@ -340,8 +339,8 @@ synchronized HttpClient put(HttpClient h) { HttpClient staleClient = null; assert KeepAliveCache.getMaxConnections() > 0; if (size() >= KeepAliveCache.getMaxConnections()) { - // remove oldest connection - staleClient = removeLast().hc; + // remove oldest connection + staleClient = removeLast().hc; } addFirst(new KeepAliveEntry(h, System.currentTimeMillis())); // close after releasing the locks