Merge branch 'jetty-9.4.x' of github.com:eclipse/jetty.project into jetty-9.4.x

This commit is contained in:
Joakim Erdfelt 2018-06-01 13:32:24 -05:00
commit 7af2eecf6a
6 changed files with 96 additions and 207 deletions

View File

@ -274,7 +274,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Max queue size {} exceeded by {} for {}", client.getMaxRequestsQueuedPerDestination(), request, this); LOG.debug("Max queue size {} exceeded by {} for {}", client.getMaxRequestsQueuedPerDestination(), request, this);
request.abort(new RejectedExecutionException("Max requests per destination " + client.getMaxRequestsQueuedPerDestination() + " exceeded for " + this)); request.abort(new RejectedExecutionException("Max requests queued per destination " + client.getMaxRequestsQueuedPerDestination() + " exceeded for " + this));
} }
} }
else else

View File

@ -24,8 +24,8 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Exchanger; import java.util.concurrent.Exchanger;
@ -189,114 +189,24 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
// Get the server side endpoint // Get the server side endpoint
EndPoint endPoint = exchanger.exchange(null,10,TimeUnit.SECONDS); EndPoint endPoint = exchanger.exchange(null,10,TimeUnit.SECONDS);
if (endPoint instanceof SslConnection.DecryptedEndPoint) if (endPoint instanceof SslConnection.DecryptedEndPoint)
endPoint=endPoint.getConnection().getEndPoint(); endPoint = ((SslConnection.DecryptedEndPoint)endPoint).getSslConnection().getEndPoint();
// read the response // read the response
String result=IO.toString(is); String result=IO.toString(is);
Assert.assertThat("OK",result, Matchers.containsString("200 OK")); Assert.assertThat(result, Matchers.containsString("200 OK"));
// check client reads EOF
Assert.assertEquals(-1, is.read());
// wait for idle timeout
TimeUnit.MILLISECONDS.sleep(3 * MAX_IDLE_TIME);
// further writes will get broken pipe or similar
try
{
for (int i=0;i<1000;i++)
{
os.write((
"GET / HTTP/1.0\r\n"+
"host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+
"\r\n").getBytes("utf-8"));
os.flush();
}
Assert.fail("half close should have timed out");
}
catch(SocketException e)
{
// expected
}
// check the server side is closed
Assert.assertFalse(endPoint.isOpen());
}
@Test(timeout=60000)
public void testMaxIdleWithRequest10ClientIgnoresClose() throws Exception
{
final Exchanger<EndPoint> exchanger = new Exchanger<>();
configureServer(new HelloWorldHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
try
{
exchanger.exchange(baseRequest.getHttpChannel().getEndPoint());
}
catch (Exception e)
{
e.printStackTrace();
}
super.handle(target, baseRequest, request, response);
}
});
Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000);
Assert.assertFalse(client.isClosed());
OutputStream os=client.getOutputStream();
InputStream is=client.getInputStream();
os.write((
"GET / HTTP/1.0\r\n"+
"host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: close\r\n"+
"\r\n").getBytes("utf-8"));
os.flush();
// Get the server side endpoint
EndPoint endPoint = exchanger.exchange(null,10,TimeUnit.SECONDS);
if (endPoint instanceof SslConnection.DecryptedEndPoint)
endPoint=endPoint.getConnection().getEndPoint();
// read the response
String result=IO.toString(is);
Assert.assertThat("OK",result, Matchers.containsString("200 OK"));
// check client reads EOF // check client reads EOF
Assert.assertEquals(-1, is.read()); Assert.assertEquals(-1, is.read());
Assert.assertTrue(endPoint.isOutputShutdown()); Assert.assertTrue(endPoint.isOutputShutdown());
Thread.sleep(2 * MAX_IDLE_TIME); // wait for idle timeout
TimeUnit.MILLISECONDS.sleep(2 * MAX_IDLE_TIME);
// further writes will get broken pipe or similar
try
{
long end=TimeUnit.NANOSECONDS.toMillis(System.nanoTime())+MAX_IDLE_TIME+3000;
while (TimeUnit.NANOSECONDS.toMillis(System.nanoTime())<end)
{
os.write("THIS DATA SHOULD NOT BE PARSED!\n\n".getBytes("utf-8"));
os.flush();
Thread.sleep(100);
}
Assert.fail("half close should have timed out");
}
catch(SocketException e)
{
// expected
// Give the SSL onClose time to act
Thread.sleep(100);
}
// check the server side is closed // check the server side is closed
Assert.assertFalse(endPoint.isOpen()); Assert.assertFalse(endPoint.isOpen());
Object transport = endPoint.getTransport();
if (transport instanceof Channel)
Assert.assertFalse(((Channel)transport).isOpen());
} }
@Test(timeout=60000) @Test(timeout=60000)
@ -343,37 +253,24 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
// Get the server side endpoint // Get the server side endpoint
EndPoint endPoint = exchanger.exchange(null,10,TimeUnit.SECONDS); EndPoint endPoint = exchanger.exchange(null,10,TimeUnit.SECONDS);
if (endPoint instanceof SslConnection.DecryptedEndPoint)
endPoint = ((SslConnection.DecryptedEndPoint)endPoint).getSslConnection().getEndPoint();
// read the response // read the response
IO.toString(is); IO.toString(is);
// check client reads EOF // check client reads EOF
Assert.assertEquals(-1, is.read()); Assert.assertEquals(-1, is.read());
Assert.assertTrue(endPoint.isOutputShutdown());
TimeUnit.MILLISECONDS.sleep(3*MAX_IDLE_TIME); // The server has shutdown the output, the client does not close,
// the server should idle timeout and close the connection.
TimeUnit.MILLISECONDS.sleep(2 * MAX_IDLE_TIME);
// further writes will get broken pipe or similar
try
{
for (int i=0;i<1000;i++)
{
os.write((
"GET / HTTP/1.0\r\n"+
"host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+
"\r\n").getBytes("utf-8"));
os.flush();
}
Assert.fail("half close should have timed out");
}
catch(SocketException e)
{
// expected
}
// check the server side is closed
Assert.assertFalse(endPoint.isOpen()); Assert.assertFalse(endPoint.isOpen());
Object transport = endPoint.getTransport();
if (transport instanceof Channel)
Assert.assertFalse(((Channel)transport).isOpen());
} }
@Test(timeout=60000) @Test(timeout=60000)

View File

@ -18,16 +18,6 @@
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
@ -64,9 +54,16 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
/** import static org.hamcrest.Matchers.containsString;
* import static org.hamcrest.Matchers.greaterThanOrEqualTo;
*/ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@RunWith(AdvancedRunner.class) @RunWith(AdvancedRunner.class)
public abstract class HttpServerTestBase extends HttpServerTestFixture public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
@ -214,19 +211,23 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
int maxHeaderSize = 1000;
_httpConfiguration.setRequestHeaderSize(maxHeaderSize);
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()); try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
StacklessLogging stackless = new StacklessLogging(HttpConnection.class)) StacklessLogging stackless = new StacklessLogging(HttpConnection.class))
{ {
((AbstractLogger)Log.getLogger(HttpConnection.class)).info("expect URI is too large, then ISE extra data ..."); Log.getLogger(HttpConnection.class).info("expect URI is too large");
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
byte[] buffer = new byte[64 * 1024]; // Take into account the initial bytes for the HTTP method.
byte[] buffer = new byte[5 + maxHeaderSize];
buffer[0]='G'; buffer[0]='G';
buffer[1]='E'; buffer[1]='E';
buffer[2]='T'; buffer[2]='T';
buffer[3]=' '; buffer[3]=' ';
buffer[4]='/'; buffer[4]='/';
Arrays.fill(buffer, 5,buffer.length-1,(byte)'A'); Arrays.fill(buffer, 5, buffer.length, (byte)'A');
os.write(buffer); os.write(buffer);
os.flush(); os.flush();

View File

@ -27,14 +27,11 @@ import java.net.Socket;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.handler.HotSwapHandler; import org.eclipse.jetty.server.handler.HotSwapHandler;
import org.eclipse.jetty.toolchain.test.PropertyFlag; import org.eclipse.jetty.toolchain.test.PropertyFlag;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
@ -269,12 +266,4 @@ public class HttpServerTestFixture
} }
public final static HostnameVerifier __hostnameverifier = new HostnameVerifier()
{
@Override
public boolean verify(String hostname, SSLSession session)
{
return true;
}
};
} }

View File

@ -18,13 +18,6 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -34,7 +27,6 @@ import java.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyStore; import java.security.KeyStore;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -58,31 +50,83 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Scheduler;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Assume; import org.junit.Assume;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/** /**
* HttpServer Tester. * HttpServer Tester.
*/ */
public class SelectChannelServerSslTest extends HttpServerTestBase public class SelectChannelServerSslTest extends HttpServerTestBase
{ {
static SSLContext __sslContext; private SSLContext _sslContext;
public SelectChannelServerSslTest()
{ {
_scheme="https"; _scheme="https";
} }
@Before
public void init() throws Exception
{
String keystorePath = MavenTestingUtils.getTestResourcePath("keystore").toString();
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(keystorePath);
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
sslContextFactory.setTrustStorePath(keystorePath);
sslContextFactory.setTrustStorePassword("storepwd");
ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory();
ServerConnector connector = new ServerConnector(_server, null, null, pool, 1, 1, AbstractConnectionFactory.getFactories(sslContextFactory, httpConnectionFactory));
SecureRequestCustomizer secureRequestCustomer = new SecureRequestCustomizer();
secureRequestCustomer.setSslSessionAttribute("SSL_SESSION");
httpConnectionFactory.getHttpConfiguration().addCustomizer(secureRequestCustomer);
startServer(connector);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream stream = sslContextFactory.getKeyStoreResource().getInputStream())
{
keystore.load(stream, "storepwd".toCharArray());
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
_sslContext = SSLContext.getInstance("TLS");
_sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
try
{
// Client configuration in case we use HttpsURLConnection.
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, SslContextFactory.TRUST_ALL_CERTS, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
@Override @Override
protected Socket newSocket(String host, int port) throws Exception protected Socket newSocket(String host, int port) throws Exception
{ {
Socket socket = __sslContext.getSocketFactory().createSocket(host,port); Socket socket = _sslContext.getSocketFactory().createSocket(host,port);
socket.setSoTimeout(10000); socket.setSoTimeout(10000);
socket.setTcpNoDelay(true); socket.setTcpNoDelay(true);
socket.setSoLinger(false,0); socket.setSoLinger(false,0);
@ -94,19 +138,19 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
{ {
// Don't run on Windows (buggy JVM) // Don't run on Windows (buggy JVM)
Assume.assumeTrue(!OS.IS_WINDOWS); Assume.assumeTrue(!OS.IS_WINDOWS);
try try
{ {
super.testFullMethod(); super.testFullMethod();
} }
catch (SocketException e) catch (SocketException e)
{ {
// TODO This needs to be investigated #2244 // TODO This needs to be investigated #2244
Log.getLogger(SslConnection.class).warn("Close overtook 400 response"); Log.getLogger(SslConnection.class).warn("Close overtook 400 response");
} }
catch (SSLException e) catch (SSLException e)
{ {
// TODO This needs to be investigated #2244 // TODO This needs to be investigated #2244
if (e.getCause() instanceof SocketException) if (e.getCause() instanceof SocketException)
Log.getLogger(SslConnection.class).warn("Close overtook 400 response"); Log.getLogger(SslConnection.class).warn("Close overtook 400 response");
else else
@ -135,49 +179,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
super.testFullHeader(); super.testFullHeader();
} }
@Before
public void init() throws Exception
{
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(keystorePath);
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
sslContextFactory.setTrustStorePath(keystorePath);
sslContextFactory.setTrustStorePassword("storepwd");
ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory();
ServerConnector connector = new ServerConnector(_server,(Executor)null,(Scheduler)null,pool, 1, 1, AbstractConnectionFactory.getFactories(sslContextFactory,httpConnectionFactory));
SecureRequestCustomizer secureRequestCustomer = new SecureRequestCustomizer();
secureRequestCustomer.setSslSessionAttribute("SSL_SESSION");
httpConnectionFactory.getHttpConfiguration().addCustomizer(secureRequestCustomer);
startServer(connector);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream stream = sslContextFactory.getKeyStoreResource().getInputStream())
{
keystore.load(stream, "storepwd".toCharArray());
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
__sslContext = SSLContext.getInstance("TLS");
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
try
{
HttpsURLConnection.setDefaultHostnameVerifier(__hostnameverifier);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, SslContextFactory.TRUST_ALL_CERTS, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
@Override @Override
public void testBlockingWhileReadingRequestContent() throws Exception public void testBlockingWhileReadingRequestContent() throws Exception
{ {

View File

@ -496,7 +496,8 @@ public class QueuedThreadPool extends ContainerLifeCycle implements SizedThreadP
@ManagedAttribute("number of busy threads in the pool") @ManagedAttribute("number of busy threads in the pool")
public int getBusyThreads() public int getBusyThreads()
{ {
return getThreads() - getIdleThreads(); int reserved = _tryExecutor instanceof ReservedThreadExecutor ? ((ReservedThreadExecutor)_tryExecutor).getAvailable() : 0;
return getThreads() - getIdleThreads() - reserved;
} }
/** /**