JETTY-1249 changes to ensure maxIdleTime applied to connections

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2110 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Jan Bartel 2010-07-13 02:06:59 +00:00
parent 9612eb956a
commit c46d01c789
10 changed files with 338 additions and 134 deletions

View File

@ -47,6 +47,24 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
private boolean _open;
private volatile long _idleTimestamp;
/* ------------------------------------------------------------ */
public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key, int maxIdleTime)
throws IOException
{
super(channel, maxIdleTime);
_manager = selectSet.getManager();
_selectSet = selectSet;
_dispatched = false;
_redispatched = false;
_open=true;
_key = key;
_connection = _manager.newConnection(channel,this);
scheduleIdle();
}
/* ------------------------------------------------------------ */
public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key)
throws IOException
@ -64,7 +82,6 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
scheduleIdle();
}
/* ------------------------------------------------------------ */
public SelectionKey getSelectionKey()
{

View File

@ -63,6 +63,20 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
private final boolean _debug = __log.isDebugEnabled(); // snapshot debug status for optimizer
/* ------------------------------------------------------------ */
public SslSelectChannelEndPoint(Buffers buffers,SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey key, SSLEngine engine, int maxIdleTime)
throws IOException
{
super(channel,selectSet,key, maxIdleTime);
_buffers=buffers;
// ssl
_engine=engine;
_session=engine.getSession();
if (_debug) __log.debug(_session+" channel="+channel);
}
/* ------------------------------------------------------------ */
public SslSelectChannelEndPoint(Buffers buffers,SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey key, SSLEngine engine)
throws IOException
@ -76,7 +90,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
if (_debug) __log.debug(_session+" channel="+channel);
}
/* ------------------------------------------------------------ */
private void needOutBuffer()
{

View File

@ -304,7 +304,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
/* ------------------------------------------------------------ */
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
return new SelectChannelEndPoint(channel,selectSet,key);
return new SelectChannelEndPoint(channel,selectSet,key, SelectChannelConnector.this._maxIdleTime);
}
/* ------------------------------------------------------------------------------- */

View File

@ -520,7 +520,7 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
SslSelectChannelEndPoint endp = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,createSSLEngine());
SslSelectChannelEndPoint endp = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,createSSLEngine(), SslSelectChannelConnector.this._maxIdleTime);
endp.setAllowRenegotiate(_allowRenegotiate);
return endp;
}

View File

@ -0,0 +1,31 @@
// ========================================================================
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
import org.eclipse.jetty.server.nio.BlockingChannelConnector;
import org.junit.BeforeClass;
public class BlockingConnectorTimeoutTest extends ConnectorTimeoutTest
{
@BeforeClass
public static void init() throws Exception
{
BlockingChannelConnector connector = new BlockingChannelConnector();
connector.setMaxIdleTime(500); //500msec max idle
startServer(connector);
}
}

View File

@ -38,7 +38,7 @@ public class BusySelectChannelServerTest extends HttpServerTestBase
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
return new SelectChannelEndPoint(channel,selectSet,key)
return new SelectChannelEndPoint(channel,selectSet,key, _maxIdleTime)
{
int write;
int read;

View File

@ -0,0 +1,90 @@
// ========================================================================
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.IO;
import org.junit.Assert;
import org.junit.Test;
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{
@Test
public void testSelectConnectorMaxIdleWithRequest() throws Exception
{
/*
* Test not working for Blocking connector
configureServer(new EchoHandler());
Socket client=new Socket(HOST,_connector.getLocalPort());
assertFalse(client.isClosed());
OutputStream os=client.getOutputStream();
InputStream is=client.getInputStream();
String content="Wibble";
byte[] contentB=content.getBytes("utf-8");
os.write((
"POST /echo HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
"content-type: text/plain; charset=utf-8\r\n"+
"content-length: "+contentB.length+"\r\n"+
"\r\n").getBytes("utf-8"));
os.write(contentB);
String in = IO.toString(is);
System.err.println(in);
Thread.sleep(600);
assertEquals(-1, is.read());
*/
}
@Test
public void testSelectConnectorMaxIdleNoRequest() throws Exception
{
/* Test is not working for Select and Blocking connectors - gregw to look at the SelectorManager and the idle timeout
configureServer(new EchoHandler());
Socket client=new Socket(HOST,_connector.getLocalPort());
OutputStream os=client.getOutputStream();
assertFalse(client.isClosed());
Thread.sleep(1100);
try
{
os.write(("xx").getBytes("utf-8"));
Assert.fail("Connection not closed");
}
catch (IOException e)
{
//expected result
}
*/
}
}

View File

@ -13,6 +13,10 @@
package org.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -26,27 +30,20 @@ import java.net.Socket;
import java.net.URL;
import java.util.Arrays;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.IO;
import org.junit.AfterClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
/**
*
*/
public abstract class HttpServerTestBase
public abstract class HttpServerTestBase extends HttpServerTestFixture
{
private static final boolean stress = Boolean.getBoolean("STRESS");
/** The request. */
private static final String REQUEST1_HEADER="POST / HTTP/1.0\n"+"Host: localhost\n"+"Content-Type: text/xml; charset=utf-8\n"+"Connection: close\n"+"Content-Length: ";
private static final String REQUEST1_CONTENT="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
@ -99,37 +96,9 @@ public abstract class HttpServerTestBase
"\n"+
RESPONSE2_CONTENT;
// Useful constants
private static final long PAUSE=10L;
private static final int LOOPS=stress?250:25;
private static final String HOST="localhost";
private static Server _server;
private static Connector _connector;
protected static void startServer(Connector connector) throws Exception
{
_server = new Server();
_connector = connector;
_server.addConnector(_connector);
_server.setHandler(new HandlerWrapper());
_server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
_server.stop();
_server.join();
}
protected void configureServer(Handler handler) throws Exception
{
HandlerWrapper current = (HandlerWrapper)_server.getHandler();
current.stop();
current.setHandler(handler);
current.start();
}
/*
* Feed the server the entire request at once.
@ -729,96 +698,4 @@ public abstract class HttpServerTestBase
Thread.sleep(PAUSE);
}
private static class EchoHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
if (request.getContentType()!=null)
response.setContentType(request.getContentType());
if (request.getParameter("charset")!=null)
response.setCharacterEncoding(request.getParameter("charset"));
else if (request.getCharacterEncoding()!=null)
response.setCharacterEncoding(request.getCharacterEncoding());
PrintWriter writer=response.getWriter();
BufferedReader reader=request.getReader();
int count=0;
String line;
while ((line=reader.readLine())!=null)
{
writer.print(line);
writer.print("\n");
count+=line.length();
}
if (count==0)
throw new IllegalStateException("no input recieved");
// just to be difficult
reader.close();
writer.close();
if (reader.read()>=0)
throw new IllegalStateException("Not closed");
}
}
private static class HelloWorldHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
response.getOutputStream().print("Hello world\r\n");
}
}
private static class DataHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
InputStream in = request.getInputStream();
String input=IO.toString(in);
String tmp = request.getParameter("writes");
int writes=Integer.parseInt(tmp==null?"10":tmp);
tmp = request.getParameter("block");
int block=Integer.parseInt(tmp==null?"10":tmp);
String encoding=request.getParameter("encoding");
String chars=request.getParameter("chars");
String chunk = (input+"\u0a870123456789A\u0a87CDEFGHIJKLMNOPQRSTUVWXYZ\u0250bcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
.substring(0,block);
response.setContentType("text/plain");
if (encoding==null)
{
byte[] bytes=chunk.getBytes("ISO-8859-1");
OutputStream out=response.getOutputStream();
for (int i=0;i<writes;i++)
out.write(bytes);
}
else if ("true".equals(chars))
{
response.setCharacterEncoding(encoding);
Writer out=response.getWriter();
char[] c=chunk.toCharArray();
for (int i=0;i<writes;i++)
out.write(c);
}
else
{
response.setCharacterEncoding(encoding);
Writer out=response.getWriter();
for (int i=0;i<writes;i++)
out.write(chunk);
}
}
}
}

View File

@ -0,0 +1,147 @@
package org.eclipse.jetty.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.IO;
import org.junit.AfterClass;
public class HttpServerTestFixture
{ // Useful constants
protected static final boolean stress = Boolean.getBoolean("STRESS");
protected static final long PAUSE=10L;
protected static final int LOOPS=stress?250:25;
protected static final String HOST="localhost";
protected static Server _server;
protected static Connector _connector;
protected static void startServer(Connector connector) throws Exception
{
_server = new Server();
_connector = connector;
_server.addConnector(_connector);
_server.setHandler(new HandlerWrapper());
_server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
_server.stop();
_server.join();
}
protected void configureServer(Handler handler) throws Exception
{
HandlerWrapper current = (HandlerWrapper)_server.getHandler();
current.stop();
current.setHandler(handler);
current.start();
}
protected static class EchoHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
if (request.getContentType()!=null)
response.setContentType(request.getContentType());
if (request.getParameter("charset")!=null)
response.setCharacterEncoding(request.getParameter("charset"));
else if (request.getCharacterEncoding()!=null)
response.setCharacterEncoding(request.getCharacterEncoding());
PrintWriter writer=response.getWriter();
BufferedReader reader=request.getReader();
int count=0;
String line;
while ((line=reader.readLine())!=null)
{
writer.print(line);
writer.print("\n");
count+=line.length();
}
if (count==0)
throw new IllegalStateException("no input recieved");
// just to be difficult
reader.close();
writer.close();
if (reader.read()>=0)
throw new IllegalStateException("Not closed");
}
}
protected static class HelloWorldHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
response.getOutputStream().print("Hello world\r\n");
}
}
protected static class DataHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
InputStream in = request.getInputStream();
String input=IO.toString(in);
String tmp = request.getParameter("writes");
int writes=Integer.parseInt(tmp==null?"10":tmp);
tmp = request.getParameter("block");
int block=Integer.parseInt(tmp==null?"10":tmp);
String encoding=request.getParameter("encoding");
String chars=request.getParameter("chars");
String chunk = (input+"\u0a870123456789A\u0a87CDEFGHIJKLMNOPQRSTUVWXYZ\u0250bcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
.substring(0,block);
response.setContentType("text/plain");
if (encoding==null)
{
byte[] bytes=chunk.getBytes("ISO-8859-1");
OutputStream out=response.getOutputStream();
for (int i=0;i<writes;i++)
out.write(bytes);
}
else if ("true".equals(chars))
{
response.setCharacterEncoding(encoding);
Writer out=response.getWriter();
char[] c=chunk.toCharArray();
for (int i=0;i<writes;i++)
out.write(c);
}
else
{
response.setCharacterEncoding(encoding);
Writer out=response.getWriter();
for (int i=0;i<writes;i++)
out.write(chunk);
}
}
}
}

View File

@ -0,0 +1,29 @@
// ========================================================================
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.BeforeClass;
public class SelectConnectorTimeoutTest extends ConnectorTimeoutTest
{
@BeforeClass
public static void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
connector.setMaxIdleTime(500); //500msec max idle
startServer(connector);
}
}