Merge remote-tracking branch 'origin/master' into jetty-8

Conflicts:
	jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
This commit is contained in:
Greg Wilkins 2012-01-12 11:01:03 +11:00
commit b8e0258faf
8 changed files with 182 additions and 66 deletions

View File

@ -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<Object>()
{
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<Object>()
{
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<Object>()
{
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));

View File

@ -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

View File

@ -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())

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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));

View File

@ -53,12 +53,6 @@
<outputDirectory>${project.build.directory}/webapps</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-jetty-distro</id>
<phase>process-test-resources</phase>