diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java index abcdce4d001..b417ce0cc22 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java @@ -45,7 +45,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import static org.hamcrest.Matchers.greaterThan; @@ -226,6 +225,7 @@ public class SslBytesServerTest extends SslBytesTest Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -304,6 +304,7 @@ public class SslBytesServerTest extends SslBytesTest Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -333,6 +334,129 @@ public class SslBytesServerTest extends SslBytesTest proxy.flushToClient(record); } + @Test + public void testClientHelloIncompleteThenReset() throws Exception + { + final SSLSocket client = newClient(); + + threadPool.submit(new Callable() + { + public Object call() throws Exception + { + client.startHandshake(); + return null; + } + }); + + // Client Hello + TLSRecord record = proxy.readFromClient(); + byte[] bytes = record.getBytes(); + byte[] chunk1 = new byte[2 * bytes.length / 3]; + System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); + proxy.flushToServer(100, chunk1); + + proxy.sendRSTToServer(); + + // Wait a while to detect spinning + TimeUnit.MILLISECONDS.sleep(500); + Assert.assertThat(sslHandles.get(), lessThan(20)); + Assert.assertThat(sslFlushes.get(), lessThan(20)); + Assert.assertThat(httpParses.get(), lessThan(50)); + + client.close(); + } + + @Test + public void testClientHelloThenReset() throws Exception + { + final SSLSocket client = newClient(); + + threadPool.submit(new Callable() + { + public Object call() throws Exception + { + client.startHandshake(); + return null; + } + }); + + // Client Hello + TLSRecord record = proxy.readFromClient(); + Assert.assertNotNull(record); + proxy.flushToServer(record); + + proxy.sendRSTToServer(); + + // Wait a while to detect spinning + TimeUnit.MILLISECONDS.sleep(500); + Assert.assertThat(sslHandles.get(), lessThan(20)); + Assert.assertThat(sslFlushes.get(), lessThan(20)); + Assert.assertThat(httpParses.get(), lessThan(50)); + + client.close(); + } + + @Test + public void testHandshakeThenReset() throws Exception + { + final SSLSocket client = newClient(); + + SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); + client.startHandshake(); + Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); + + proxy.sendRSTToServer(); + + // Wait a while to detect spinning + TimeUnit.MILLISECONDS.sleep(500); + Assert.assertThat(sslHandles.get(), lessThan(20)); + Assert.assertThat(sslFlushes.get(), lessThan(20)); + Assert.assertThat(httpParses.get(), lessThan(50)); + + client.close(); + } + + @Test + public void testRequestIncompleteThenReset() throws Exception + { + final SSLSocket client = newClient(); + + SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); + client.startHandshake(); + Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); + + threadPool.submit(new Callable() + { + public Object call() throws Exception + { + OutputStream clientOutput = client.getOutputStream(); + clientOutput.write(("" + + "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "\r\n").getBytes("UTF-8")); + clientOutput.flush(); + return null; + } + }); + + // Application data + TLSRecord record = proxy.readFromClient(); + byte[] bytes = record.getBytes(); + byte[] chunk1 = new byte[2 * bytes.length / 3]; + System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); + proxy.flushToServer(100, chunk1); + + proxy.sendRSTToServer(); + + // Wait a while to detect spinning + TimeUnit.MILLISECONDS.sleep(500); + Assert.assertThat(sslHandles.get(), lessThan(20)); + Assert.assertThat(sslFlushes.get(), lessThan(20)); + Assert.assertThat(httpParses.get(), lessThan(50)); + + client.close(); + } + @Test public void testRequestResponse() throws Exception { @@ -377,6 +501,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -468,6 +593,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(750)); Assert.assertThat(sslFlushes.get(), lessThan(750)); Assert.assertThat(httpParses.get(), lessThan(150)); @@ -492,20 +618,12 @@ public class SslBytesServerTest extends SslBytesTest proxy.flushToClient(record); } - /** - * TODO - * Currently this test does not pass. - * The problem is a mix of Java not being able to perform SSL half closes - * (but SSL supporting it), and the current implementation in Jetty. - * See the test below, that passes and whose only difference is that we - * delay the output shutdown from the client. - * - * @throws Exception if the test fails - */ - @Ignore @Test public void testRequestWithCloseAlertAndShutdown() throws Exception { + // See next test on why we only run in Linux + Assume.assumeTrue(OS.IS_LINUX); + final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); @@ -555,10 +673,11 @@ public class SslBytesServerTest extends SslBytesTest Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); // We can't forward to the client, its socket is already closed - // Socket close - record = proxy.readFromClient(); - Assert.assertNull(String.valueOf(record), record); - proxy.flushToServer(record); + // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); + Assert.assertThat(sslHandles.get(), lessThan(20)); + Assert.assertThat(sslFlushes.get(), lessThan(20)); + Assert.assertThat(httpParses.get(), lessThan(50)); // Socket close record = proxy.readFromServer(); @@ -569,21 +688,16 @@ public class SslBytesServerTest extends SslBytesTest @Test public void testRequestWithCloseAlert() throws Exception { - if ( !OS.IS_LINUX ) - { - // currently we are ignoring this test on anything other then linux - - //http://tools.ietf.org/html/rfc2246#section-7.2.1 + // Currently we are ignoring this test on anything other then linux + // http://tools.ietf.org/html/rfc2246#section-7.2.1 + + // TODO (react to this portion which seems to allow win/mac behavior) + // It is required that the other party respond with a close_notify alert of its own + // and close down the connection immediately, discarding any pending writes. It is not + // required for the initiator of the close to wait for the responding + // close_notify alert before closing the read side of the connection. + Assume.assumeTrue(OS.IS_LINUX); - // TODO (react to this portion which seems to allow win/mac behavior) - //It is required that the other party respond with a close_notify alert of its own - //and close down the connection immediately, discarding any pending writes. It is not - //required for the initiator of the close to wait for the responding - //close_notify alert before closing the read side of the connection. - return; - } - - final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); @@ -634,6 +748,7 @@ public class SslBytesServerTest extends SslBytesTest // We can't forward to the client, its socket is already closed // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -692,6 +807,7 @@ public class SslBytesServerTest extends SslBytesTest proxy.flushToClient(record); // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -700,7 +816,7 @@ public class SslBytesServerTest extends SslBytesTest } @Test - public void testRequestWithBigContentWriteBlockedAndResetException() throws Exception + public void testRequestWithBigContentWriteBlockedThenReset() throws Exception { final SSLSocket client = newClient(); @@ -744,11 +860,10 @@ public class SslBytesServerTest extends SslBytesTest // connection, and this will cause an exception in the // server that is trying to write the data - proxy.resetServer(); + proxy.sendRSTToServer(); // Wait a while to detect spinning - TimeUnit.SECONDS.sleep(1); - + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -762,17 +877,17 @@ public class SslBytesServerTest extends SslBytesTest if ( !OS.IS_LINUX ) { // currently we are ignoring this test on anything other then linux - + //http://tools.ietf.org/html/rfc2246#section-7.2.1 - // TODO (react to this portion which seems to allow win/mac behavior) - //It is required that the other party respond with a close_notify alert of its own + // TODO (react to this portion which seems to allow win/mac behavior) + //It is required that the other party respond with a close_notify alert of its own //and close down the connection immediately, discarding any pending writes. It is not //required for the initiator of the close to wait for the responding //close_notify alert before closing the read side of the connection. return; } - + final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); @@ -831,6 +946,7 @@ public class SslBytesServerTest extends SslBytesTest // We can't forward to the client, its socket is already closed // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -900,6 +1016,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -953,6 +1070,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(150)); @@ -974,6 +1092,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(150)); @@ -1105,6 +1224,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); @@ -1264,6 +1384,7 @@ public class SslBytesServerTest extends SslBytesTest } // Check that we did not spin + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(100)); @@ -1312,7 +1433,7 @@ public class SslBytesServerTest extends SslBytesTest // Client should close the socket, but let's hold it open. // Check that we did not spin - TimeUnit.MILLISECONDS.sleep(100); + TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java index 4c8266180c4..9b13bc30e02 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java @@ -320,7 +320,7 @@ public abstract class SslBytesTest return latch.await(time, unit); } - public void resetServer() throws IOException + public void sendRSTToServer() throws IOException { // Calling setSoLinger(true, 0) causes close() // to send a RST instead of a FIN, causing an diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java index f4a0d527b97..fa8a02d505a 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java @@ -246,8 +246,7 @@ public class ChannelEndPoint implements EndPoint } catch (IOException x) { - LOG.debug(x.toString()); - LOG.ignore(x); + LOG.debug("Exception while filling", x); try { if (_channel.isOpen()) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java index 876db22112d..d531dc606e9 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java @@ -541,6 +541,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection switch(result.getStatus()) { case BUFFER_UNDERFLOW: + if (_endp.isInputShutdown()) + _inbound.clear(); break; case BUFFER_OVERFLOW: @@ -598,7 +600,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection { return _engine; } - + public AsyncEndPoint getEndpoint() { return _aEndp; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java index 59e66626e69..cbd9b7ecf39 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java @@ -45,6 +45,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async _asyncEndp=(AsyncEndPoint)endpoint; } + @Override public Connection handle() throws IOException { Connection connection = this; @@ -54,10 +55,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async try { setCurrentConnection(this); - + // don't check for idle while dispatched (unless blocking IO is done). _asyncEndp.setCheckForIdle(false); - + // While progress and the connection has not changed while (progress && connection==this) @@ -67,7 +68,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async { // Handle resumed request if (_request._async.isAsync()) - { + { if (_request._async.isDispatchable()) handleRequest(); } @@ -126,7 +127,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async } else if (_request.getAsyncContinuation().isAsyncStarted()) { - // The request is suspended, so even though progress has been made, + // The request is suspended, so even though progress has been made, // exit the while loop by setting progress to false LOG.debug("suspended {}",this); progress=false; @@ -137,21 +138,18 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async finally { setCurrentConnection(null); - + // If we are not suspended if (!_request.getAsyncContinuation().isAsyncStarted()) { // return buffers _parser.returnBuffers(); _generator.returnBuffers(); - } - - // reenable idle checking unless request is suspended - if(!_request.getAsyncContinuation().isAsyncStarted()) - { + + // reenable idle checking unless request is suspended _asyncEndp.setCheckForIdle(true); } - + // Safety net to catch spinning if (some_progress) _total_no_progress=0; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java index 9fcdfb6d532..f7a834f9619 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java @@ -13,7 +13,6 @@ package org.eclipse.jetty.server; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; @@ -84,7 +83,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException { - String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n"; + String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n"; if (content == null) request += "\r\n"; @@ -97,11 +96,13 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest { SelectChannelConnector connector = (SelectChannelConnector)_connector; Socket socket = new Socket((String)null,connector.getLocalPort()); + socket.setSoTimeout(10 * MAX_IDLE_TIME); socket.getOutputStream().write(request.getBytes("UTF-8")); InputStream inputStream = socket.getInputStream(); + long start = System.currentTimeMillis(); String response = IO.toString(inputStream); - Thread.sleep(500); - assertEquals("Socket should be closed and return -1 on reading",-1,socket.getInputStream().read()); + long timeElapsed = System.currentTimeMillis() - start; + assertTrue("Time elapsed should be at least MAX_IDLE_TIME",timeElapsed > MAX_IDLE_TIME); return response; } diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java index 9b4af2d27c9..fb39dde130f 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SafariWebsocketDraft0Test.java @@ -95,10 +95,11 @@ public class SafariWebsocketDraft0Test CaptureSocket socket = servlet.captures.get(0); Assert.assertThat("CaptureSocket",socket,notNullValue()); - Assert.assertThat("CaptureSocket.isConnected", socket.awaitConnected(1000), is(true)); + Assert.assertThat("CaptureSocket.isConnected", socket.awaitConnected(10000), is(true)); // Give servlet time to process messages - threadSleep(1,TimeUnit.SECONDS); + for (int i=0;i<100 && socket.messages.size()<5;i++) + threadSleep(100,TimeUnit.MILLISECONDS); // Should have captured 5 messages. Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5)); diff --git a/tests/test-integration/pom.xml b/tests/test-integration/pom.xml index 561d51a27aa..4d248c79c91 100644 --- a/tests/test-integration/pom.xml +++ b/tests/test-integration/pom.xml @@ -53,12 +53,6 @@ ${project.build.directory}/webapps - - - - org.apache.maven.plugins - maven-dependency-plugin - unpack-jetty-distro process-test-resources