328199 ensure SSL closes connections when shutdownoutput is attempted

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2388 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-10-22 23:12:22 +00:00
parent e5df5d82ee
commit 72e6f5ee40
14 changed files with 126 additions and 32 deletions

View File

@ -2,6 +2,7 @@
+ 328199 Ensure blocking connectors always close socket
+ 328205 Improved SelectManager stopping
+ 328306 Serialization of FormAuthentication
+ 328332 Response.getContentType works with setHeader
jetty-7.2.0.v20101020 20 October 2010
+ 289540 added javadoc into distribution

View File

@ -21,7 +21,6 @@ import java.net.Socket;
import org.eclipse.jetty.util.StringUtil;
/**
*
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments

View File

@ -658,6 +658,9 @@ public class HttpConnection implements Connection
// send the body anyway, or close. So we no longer need to
// do anything special here.
_expect100Continue = false;
if (!_response.isCommitted())
_generator.setPersistent(false);
}
if(_endp.isOpen())

View File

@ -17,7 +17,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
@ -39,7 +38,6 @@ import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
@ -64,15 +62,6 @@ public class Response implements HttpServletResponse
*/
public final static String SET_INCLUDE_HEADER_PREFIX = "org.eclipse.jetty.server.include.";
private static final PrintWriter __nullPrintWriter;
private static final ServletOutputStream __nullServletOut;
static
{
__nullPrintWriter = new PrintWriter(IO.getNullWriter());
__nullServletOut = new NullOutput();
}
private final HttpConnection _connection;
private int _status=SC_OK;
private String _reason;
@ -472,20 +461,25 @@ public class Response implements HttpServletResponse
*/
public void setHeader(String name, String value)
{
if (_connection.isIncluding())
if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name))
setContentType(value);
else
{
if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
else
return;
}
_connection.getResponseFields().put(name, value);
if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
{
if (value==null)
_connection._generator.setContentLength(-1);
else
_connection._generator.setContentLength(Long.parseLong(value));
if (_connection.isIncluding())
{
if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
else
return;
}
_connection.getResponseFields().put(name, value);
if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
{
if (value==null)
_connection._generator.setContentLength(-1);
else
_connection._generator.setContentLength(Long.parseLong(value));
}
}
}

View File

@ -267,10 +267,24 @@ public class SocketConnector extends AbstractConnector
_connections.remove(this);
}
// ensure it really is closed and not just shutdown.
// wait for client to close, but if not, close ourselves.
try
{
_socket.close();
if (!_socket.isClosed())
{
long timestamp=System.currentTimeMillis();
int max_idle=getMaxIdleTime();
_socket.setSoTimeout(getMaxIdleTime());
int c=0;
do
{
c = _socket.getInputStream().read();
}
while (c>=0 && (System.currentTimeMillis()-timestamp)<max_idle);
if (!_socket.isClosed())
_socket.close();
}
}
catch(IOException e)
{

View File

@ -290,6 +290,7 @@ public class BlockingChannelConnector extends AbstractNIOConnector
}
_connection = _connection.handle();
}
}
catch (EofException e)
@ -315,10 +316,24 @@ public class BlockingChannelConnector extends AbstractNIOConnector
connectionClosed(_connection);
_endpoints.remove(this);
// ensure it really is closed and not just shutdown.
// wait for client to close, but if not, close ourselves.
try
{
_socket.close();
if (!_socket.isClosed())
{
long timestamp=System.currentTimeMillis();
int max_idle=getMaxIdleTime();
_socket.setSoTimeout(getMaxIdleTime());
int c=0;
do
{
c = _socket.getInputStream().read();
}
while (c>=0 && (System.currentTimeMillis()-timestamp)<max_idle);
if (!_socket.isClosed())
_socket.close();
}
}
catch(IOException e)
{

View File

@ -607,6 +607,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
@Override
public void shutdownOutput() throws IOException
{
close();
}
@Override

View File

@ -691,6 +691,48 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
}
}
@Test
public void testBlockedClient() throws Exception
{
configureServer(new HelloWorldHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
try
{
OutputStream os=client.getOutputStream();
InputStream is=client.getInputStream();
// Send a request with chunked input and expect 100
os.write((
"GET / HTTP/1.1\r\n"+
"Host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Expect: 100-continue\r\n"+
"Connection: Keep-Alive\r\n"+
"\r\n"
).getBytes());
// Never send a body.
// HelloWorldHandler does not read content, so 100 is not sent.
// So close will have to happen anyway, without reset!
os.flush();
client.setSoTimeout(2000);
long start=System.currentTimeMillis();
String in = IO.toString(is);
assertTrue(System.currentTimeMillis()-start<1000);
assertTrue(in.indexOf("Connection: close")>0);
assertTrue(in.indexOf("Hello world")>0);
}
finally
{
client.close();
}
}
/**
* Read entire response from the client. Close the output.
*

View File

@ -78,6 +78,9 @@ public class ResponseTest
assertEquals(null,response.getContentType());
response.setHeader("Content-Type","text/something");
assertEquals("text/something",response.getContentType());
response.setContentType("foo/bar");
assertEquals("foo/bar",response.getContentType());
response.getWriter();

View File

@ -68,4 +68,10 @@ public class SslSelectChannelServerTest extends HttpServerTestBase
// TODO this test uses URL, so noop for now
}
@Test
@Override
public void testBlockedClient() throws Exception
{
}
}

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.nio.BlockingChannelConnector;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.session.HashSessionManager;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
@ -88,6 +89,13 @@ public class TestServer
connector2.setConfidentialPort(8443);
server.addConnector(connector2);
// Setup Connectors
BlockingChannelConnector connector3 = new BlockingChannelConnector();
connector3.setPort(8083);
connector3.setMaxIdleTime(30000);
connector3.setConfidentialPort(8443);
server.addConnector(connector3);
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
ssl_connector.setPort(8443);
ssl_connector.setKeystore(jetty_root + "/jetty-server/src/main/config/etc/keystore");

View File

@ -721,8 +721,11 @@ public abstract class RFC2616BaseTest
response.assertStatusOK("8.2.3 expect 100");
}
/**
* Test Message Transmission Requirements -- Acceptable bad client behavior, Expect 100 with body content.
* @throws Exception failure
*
* @see <a href="http://tools.ietf.org/html/rfc2616#section-8.2">RFC 2616 (section 8.2)</a>
*/
@ -749,10 +752,15 @@ public abstract class RFC2616BaseTest
List<HttpResponseTester> responses = http.requests(req3);
System.err.println(responses);
response=responses.get(0);
System.err.println(response.getRawResponse());
response.assertStatus("8.2.3 ignored no 100",302);
response=responses.get(1);
System.err.println(response.getRawResponse());
response.assertStatus("8.2.3 ignored no 100",200);
response.assertBody("87654321\n");
}