Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2014-04-09 15:22:48 +0000
committerSimone Bordet2014-04-09 15:22:48 +0000
commit91584f36e429778a809f79500bedbb4e79788919 (patch)
tree7c9c1df3d328ae82a0157410efec0cc42c1f0994
parent28d3518004d8b117a62c9c5f07599131bbe1e951 (diff)
downloadorg.eclipse.jetty.project-91584f36e429778a809f79500bedbb4e79788919.tar.gz
org.eclipse.jetty.project-91584f36e429778a809f79500bedbb4e79788919.tar.xz
org.eclipse.jetty.project-91584f36e429778a809f79500bedbb4e79788919.zip
432452 - ConnectHandler does not timeout sockets in FIN_WAIT2.
Fixed by properly closing the socket in case of idle timeout.
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java16
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java44
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java149
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java18
4 files changed, 173 insertions, 54 deletions
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
index b983504a08..ac702037e9 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
@@ -517,8 +517,6 @@ public class ConnectHandler extends HandlerWrapper
}
}
-
-
public class ProxyToServerConnection implements AsyncConnection
{
private final CountDownLatch _ready = new CountDownLatch(1);
@@ -601,7 +599,6 @@ public class ConnectHandler extends HandlerWrapper
public void onInputShutdown() throws IOException
{
- // TODO
}
private void writeData() throws IOException
@@ -724,7 +721,11 @@ public class ConnectHandler extends HandlerWrapper
{
try
{
- shutdownOutput();
+ LOG.debug("{} idle expired", this);
+ if (_endPoint.isOutputShutdown())
+ close();
+ else
+ shutdownOutput();
}
catch(Exception e)
{
@@ -824,7 +825,6 @@ public class ConnectHandler extends HandlerWrapper
public void onInputShutdown() throws IOException
{
- // TODO
}
public long getTimeStamp()
@@ -891,7 +891,11 @@ public class ConnectHandler extends HandlerWrapper
{
try
{
- shutdownOutput();
+ LOG.debug("{} idle expired", this);
+ if (_endPoint.isOutputShutdown())
+ close();
+ else
+ shutdownOutput();
}
catch(Exception e)
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
index 8d5784d9d2..474950df52 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
@@ -33,22 +33,19 @@ import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.junit.AfterClass;
+import org.junit.After;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-/**
- * @version $Revision$ $Date$
- */
public abstract class AbstractConnectHandlerTest
{
- protected static Server server;
- protected static Connector serverConnector;
- protected static Server proxy;
- protected static Connector proxyConnector;
+ protected Server server;
+ protected Connector serverConnector;
+ protected Server proxy;
+ protected Connector proxyConnector;
- protected static void startServer(Connector connector, Handler handler) throws Exception
+ protected void startServer(Connector connector, Handler handler) throws Exception
{
server = new Server();
serverConnector = connector;
@@ -57,29 +54,34 @@ public abstract class AbstractConnectHandlerTest
server.start();
}
- protected static void startProxy() throws Exception
+ protected void startProxy() throws Exception
+ {
+ startProxy(new SelectChannelConnector(), new ConnectHandler());
+ }
+
+ protected void startProxy(Connector connector, ConnectHandler connectHandler) throws Exception
{
proxy = new Server();
- proxyConnector = new SelectChannelConnector();
+ proxyConnector = connector;
proxy.addConnector(proxyConnector);
- proxy.setHandler(new ConnectHandler());
+ proxy.setHandler(connectHandler);
proxy.start();
}
- @AfterClass
- public static void stop() throws Exception
+ @After
+ public void stop() throws Exception
{
stopProxy();
stopServer();
}
- protected static void stopServer() throws Exception
+ protected void stopServer() throws Exception
{
server.stop();
server.join();
}
- protected static void stopProxy() throws Exception
+ protected void stopProxy() throws Exception
{
proxy.stop();
proxy.join();
@@ -113,7 +115,7 @@ public abstract class AbstractConnectHandlerTest
{
int readLen = 0;
int length = Integer.parseInt(headers.get("content-length"));
- body=new StringBuilder(length);
+ body = new StringBuilder(length);
try
{
for (int i = 0; i < length; ++i)
@@ -121,19 +123,17 @@ public abstract class AbstractConnectHandlerTest
char c = (char)reader.read();
body.append(c);
readLen++;
-
}
-
}
catch (SocketTimeoutException e)
{
- System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n",readLen,length);
+ System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n", readLen, length);
throw e;
}
}
else if ("chunked".equals(headers.get("transfer-encoding")))
{
- body = new StringBuilder(64*1024);
+ body = new StringBuilder(64 * 1024);
while ((line = reader.readLine()) != null)
{
if ("0".equals(line))
@@ -151,7 +151,7 @@ public abstract class AbstractConnectHandlerTest
{
e.printStackTrace();
}
-
+
int length = Integer.parseInt(line, 16);
for (int i = 0; i < length; ++i)
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
index 8371cd88c6..a68552f570 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
@@ -25,9 +25,12 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
+import java.nio.channels.SocketChannel;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
@@ -38,35 +41,40 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.io.AsyncEndPoint;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.junit.BeforeClass;
+import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
-/**
- * @version $Revision$ $Date$
- */
public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
{
- @BeforeClass
- public static void init() throws Exception
+ @Before
+ public void init() throws Exception
{
- SslSelectChannelConnector connector = new SslSelectChannelConnector();
- connector.setMaxIdleTime(3600000); // TODO remove
+ startServer(prepareServerConnector(), new ServerHandler());
+ startProxy();
+ }
+ private SslSelectChannelConnector prepareServerConnector()
+ {
+ SslSelectChannelConnector connector = new SslSelectChannelConnector();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keyStorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
-
- startServer(connector, new ServerHandler());
- startProxy();
+ return connector;
}
@Test
@@ -78,7 +86,6 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
"Host: " + hostPort + "\r\n" +
"\r\n";
Socket socket = newSocket();
- socket.setSoTimeout(3600000); // TODO remove
try
{
OutputStream output = socket.getOutputStream();
@@ -104,8 +111,8 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
request =
"GET /echo HTTP/1.1\r\n" +
- "Host: " + hostPort + "\r\n" +
- "\r\n";
+ "Host: " + hostPort + "\r\n" +
+ "\r\n";
output.write(request.getBytes("UTF-8"));
output.flush();
@@ -182,6 +189,118 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
}
}
+ @Test
+ public void testServerHalfClosesClientDoesNotCloseExpectIdleTimeout() throws Exception
+ {
+ stop();
+
+ final String uri = "/echo";
+ int idleTimeout = 2000;
+ startServer(prepareServerConnector(), new AbstractHandler()
+ {
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String requestURI = request.getRequestURI();
+ if (uri.equals(requestURI))
+ {
+ baseRequest.setHandled(true);
+ response.setHeader("Connection", "close");
+ response.setContentLength(uri.length());
+ response.getOutputStream().print(uri);
+ }
+ }
+ });
+ Connector proxyConnector = new SelectChannelConnector();
+ proxyConnector.setMaxIdleTime(idleTimeout);
+
+ final AtomicReference<EndPoint> proxyToClientEndPoint = new AtomicReference<EndPoint>();
+ final AtomicReference<EndPoint> proxyToServerEndPoint = new AtomicReference<EndPoint>();
+ ConnectHandler connectHandler = new ConnectHandler()
+ {
+ @Override
+ protected ClientToProxyConnection newClientToProxyConnection(ConcurrentMap<String, Object> context, SocketChannel channel, EndPoint endPoint, long timeStamp)
+ {
+ proxyToClientEndPoint.set(endPoint);
+ return new ClientToProxyConnection(context, channel, endPoint, timeStamp);
+ }
+
+ @Override
+ protected ProxyToServerConnection newProxyToServerConnection(ConcurrentMap<String, Object> context, Buffer buffer)
+ {
+ return new ProxyToServerConnection(context, buffer)
+ {
+ @Override
+ public void setEndPoint(AsyncEndPoint endpoint)
+ {
+ proxyToServerEndPoint.set(endpoint);
+ super.setEndPoint(endpoint);
+ }
+ };
+ }
+ };
+ connectHandler.setWriteTimeout(2 * idleTimeout);
+ startProxy(proxyConnector, connectHandler);
+
+ String hostPort = "localhost:" + serverConnector.getLocalPort();
+ String request = "" +
+ "CONNECT " + hostPort + " HTTP/1.1\r\n" +
+ "Host: " + hostPort + "\r\n" +
+ "\r\n";
+ Socket socket = newSocket();
+ try
+ {
+ OutputStream output = socket.getOutputStream();
+ BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ // Expect 200 OK from the CONNECT request
+ Response response = readResponse(input);
+ System.err.println(response);
+ assertEquals("200", response.getCode());
+
+ // Be sure the buffered input does not have anything buffered
+ assertFalse(input.ready());
+
+ // Upgrade the socket to SSL
+ SSLSocket sslSocket = wrapSocket(socket);
+ try
+ {
+ output = sslSocket.getOutputStream();
+ input = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
+
+ request = "" +
+ "GET " + uri + " HTTP/1.1\r\n" +
+ "Host: " + hostPort + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ response = readResponse(input);
+ assertEquals("200", response.getCode());
+ assertEquals(uri, response.getBody());
+
+ Thread.sleep(4 * idleTimeout);
+
+ EndPoint p2c = proxyToClientEndPoint.get();
+ assertNotNull(p2c);
+ assertFalse(p2c.isOpen());
+ EndPoint p2s = proxyToServerEndPoint.get();
+ assertNotNull(p2s);
+ assertFalse(p2s.isOpen());
+ }
+ finally
+ {
+ sslSocket.close();
+ }
+ }
+ finally
+ {
+ socket.close();
+ }
+ }
+
private SSLSocket wrapSocket(Socket socket) throws Exception
{
SSLContext sslContext = SSLContext.getInstance("SSLv3");
@@ -225,7 +344,7 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream input = httpRequest.getInputStream();
- int read = -1;
+ int read;
while ((read = input.read()) >= 0)
baos.write(read);
baos.close();
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
index a77de493d2..8cf419db1a 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
@@ -18,9 +18,6 @@
package org.eclipse.jetty.server.handler;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -32,7 +29,6 @@ import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ConcurrentMap;
-
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@@ -44,16 +40,16 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.toolchain.test.OS;
import org.junit.Assert;
-import org.junit.BeforeClass;
+import org.junit.Before;
import org.junit.Test;
-/**
- * @version $Revision$ $Date$
- */
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
public class ConnectHandlerTest extends AbstractConnectHandlerTest
{
- @BeforeClass
- public static void init() throws Exception
+ @Before
+ public void init() throws Exception
{
startServer(new SelectChannelConnector(), new ServerHandler());
startProxy();
@@ -658,7 +654,7 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream input = httpRequest.getInputStream();
- int read = -1;
+ int read;
while ((read = input.read()) >= 0)
baos.write(read);
baos.close();

Back to the top