# HG changeset patch # User jpai # Date 1567165975 -19800 # Node ID 197f36af94f304f33fba47d59ceab53d141a4464 # Parent 2172fd713350599c2b056a7f2d7d0fa0bbcc84cd 8223714: HTTPSetAuthenticatorTest could be made more resilient Summary: HTTPTestServer (in the test infrastructure) will no longer stop accepting requests if a previous request processing failed Reviewed-by: dfuchs diff -r 2172fd713350 -r 197f36af94f3 test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java --- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java Tue Sep 03 10:03:13 2019 +0200 +++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java Fri Aug 30 17:22:55 2019 +0530 @@ -980,6 +980,8 @@ implements Runnable { final ServerSocket ss; + private volatile boolean stop; + public HttpsProxyTunnel(HttpServer server, HTTPTestServer target, HttpHandler delegate) throws IOException { @@ -998,9 +1000,10 @@ @Override public void stop() { - super.stop(); - try { - ss.close(); + try (var toClose = ss) { + stop = true; + System.out.println("Server " + ss + " stop requested"); + super.stop(); } catch (IOException ex) { if (DEBUG) ex.printStackTrace(System.out); } @@ -1050,6 +1053,9 @@ if (c == '\n') break; b.appendCodePoint(c); } + if (b.length() == 0) { + return ""; + } if (b.codePointAt(b.length() -1) == '\r') { b.delete(b.length() -1, b.length()); } @@ -1059,80 +1065,121 @@ @Override public void run() { Socket clientConnection = null; - try { - while (true) { - System.out.println("Tunnel: Waiting for client at: " + ss); - Socket previous = clientConnection; + while (!stop) { + System.out.println("Tunnel: Waiting for client at: " + ss); + final Socket previous = clientConnection; + try { + clientConnection = ss.accept(); + } catch (IOException io) { try { - clientConnection = ss.accept(); - } catch (IOException io) { - if (DEBUG) io.printStackTrace(System.out); - break; - } finally { - // close the previous connection - if (previous != null) previous.close(); - } - System.out.println("Tunnel: Client accepted"); - Socket targetConnection = null; - InputStream ccis = clientConnection.getInputStream(); - OutputStream ccos = clientConnection.getOutputStream(); - Writer w = new OutputStreamWriter( - clientConnection.getOutputStream(), "UTF-8"); - PrintWriter pw = new PrintWriter(w); - System.out.println("Tunnel: Reading request line"); - String requestLine = readLine(ccis); - System.out.println("Tunnel: Request line: " + requestLine); - if (requestLine.startsWith("CONNECT ")) { - // We should probably check that the next word following - // CONNECT is the host:port of our HTTPS serverImpl. - // Some improvement for a followup! - - // Read all headers until we find the empty line that - // signals the end of all headers. - while(!requestLine.equals("")) { - System.out.println("Tunnel: Reading header: " - + (requestLine = readLine(ccis))); + ss.close(); + } catch (IOException ex) { + if (DEBUG) { + ex.printStackTrace(System.out); } - - targetConnection = new Socket( - serverImpl.getAddress().getAddress(), - serverImpl.getAddress().getPort()); - - // Then send the 200 OK response to the client - System.out.println("Tunnel: Sending " - + "HTTP/1.1 200 OK\r\n\r\n"); - pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); - pw.flush(); - } else { - // This should not happen. If it does let our serverImpl - // deal with it. - throw new IOException("Tunnel: Unexpected status line: " - + requestLine); + } + // log the reason that caused the server to stop accepting connections + if (!stop) { + System.err.println("Server will stop accepting connections due to an exception:"); + io.printStackTrace(); + } + break; + } finally { + // close the previous connection + if (previous != null) { + try { + previous.close(); + } catch (IOException e) { + // ignore + if (DEBUG) { + System.out.println("Ignoring exception that happened while closing " + + "an older connection:"); + e.printStackTrace(System.out); + } + } } - - // Pipe the input stream of the client connection to the - // output stream of the target connection and conversely. - // Now the client and target will just talk to each other. - System.out.println("Tunnel: Starting tunnel pipes"); - Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); - Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); - t1.start(); - t2.start(); - - // We have only 1 client... wait until it has finished before + } + System.out.println("Tunnel: Client accepted"); + try { + // We have only 1 client... process the current client + // request and wait until it has finished before // accepting a new connection request. - t1.join(); - t2.join(); + processRequestAndWaitToComplete(clientConnection); + } catch (IOException ioe) { + // close the client connection + try { + clientConnection.close(); + } catch (IOException io) { + // ignore + if (DEBUG) { + System.out.println("Ignoring exception that happened during client" + + " connection close:"); + io.printStackTrace(System.out); + } + } finally { + clientConnection = null; + } + } catch (Throwable t) { + // don't close the client connection for non-IOExceptions, instead + // just log it and move on to accept next connection + if (!stop) { + t.printStackTrace(); + } } - } catch (Throwable ex) { - try { - ss.close(); - } catch (IOException ex1) { - ex.addSuppressed(ex1); - } - ex.printStackTrace(System.err); } } + private void processRequestAndWaitToComplete(final Socket clientConnection) + throws IOException, InterruptedException { + final Socket targetConnection; + InputStream ccis = clientConnection.getInputStream(); + OutputStream ccos = clientConnection.getOutputStream(); + Writer w = new OutputStreamWriter( + clientConnection.getOutputStream(), "UTF-8"); + PrintWriter pw = new PrintWriter(w); + System.out.println("Tunnel: Reading request line"); + String requestLine = readLine(ccis); + System.out.println("Tunnel: Request line: " + requestLine); + if (requestLine.startsWith("CONNECT ")) { + // We should probably check that the next word following + // CONNECT is the host:port of our HTTPS serverImpl. + // Some improvement for a followup! + + // Read all headers until we find the empty line that + // signals the end of all headers. + while(!requestLine.equals("")) { + System.out.println("Tunnel: Reading header: " + + (requestLine = readLine(ccis))); + } + + targetConnection = new Socket( + serverImpl.getAddress().getAddress(), + serverImpl.getAddress().getPort()); + + // Then send the 200 OK response to the client + System.out.println("Tunnel: Sending " + + "HTTP/1.1 200 OK\r\n\r\n"); + pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + pw.flush(); + } else { + // This should not happen. If it does then consider it a + // client error and throw an IOException + System.out.println("Tunnel: Throwing an IOException due to unexpected" + + " request line: " + requestLine); + throw new IOException("Client request error - Unexpected request line"); + } + + // Pipe the input stream of the client connection to the + // output stream of the target connection and conversely. + // Now the client and target will just talk to each other. + System.out.println("Tunnel: Starting tunnel pipes"); + Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); + Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); + t1.start(); + t2.start(); + // wait for the request to complete + t1.join(); + t2.join(); + } } }