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

This commit is contained in:
Jan Bartel 2011-11-21 18:18:09 +11:00
commit 0e9449ac85
16 changed files with 1920 additions and 104 deletions

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
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.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -55,7 +56,7 @@ public class LikeJettyXml
// Setup Threadpool // Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool(); QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(100); threadPool.setMaxThreads(500);
server.setThreadPool(threadPool); server.setThreadPool(threadPool);
// Setup Connectors // Setup Connectors
@ -63,7 +64,7 @@ public class LikeJettyXml
connector.setPort(8080); connector.setPort(8080);
connector.setMaxIdleTime(30000); connector.setMaxIdleTime(30000);
connector.setConfidentialPort(8443); connector.setConfidentialPort(8443);
connector.setStatsOn(true); connector.setStatsOn(false);
server.setConnectors(new Connector[] server.setConnectors(new Connector[]
{ connector }); { connector });
@ -86,11 +87,17 @@ public class LikeJettyXml
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
}); });
ssl_connector.setStatsOn(true); ssl_connector.setStatsOn(false);
server.addConnector(ssl_connector); server.addConnector(ssl_connector);
ssl_connector.open(); ssl_connector.open();
SslSocketConnector ssl2_connector = new SslSocketConnector(cf);
ssl2_connector.setPort(8444);
ssl2_connector.setStatsOn(false);
server.addConnector(ssl2_connector);
ssl2_connector.open();
/* /*
Ajp13SocketConnector ajp = new Ajp13SocketConnector(); Ajp13SocketConnector ajp = new Ajp13SocketConnector();

View File

@ -1,6 +1,8 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -33,11 +35,26 @@ public class Curl
client.start(); client.start();
boolean async=true; boolean async=true;
boolean dump= false; boolean dump= false;
boolean verbose= false;
final CountDownLatch latch = new CountDownLatch(args.length);
int urls=0;
for (String arg : args)
{
if (!arg.startsWith("-"))
urls++;
}
final CountDownLatch latch = new CountDownLatch(urls);
for (String arg : args) for (String arg : args)
{ {
if ("--verbose".equals(arg))
{
verbose=true;
continue;
}
if ("--sync".equals(arg)) if ("--sync".equals(arg))
{ {
async=false; async=false;
@ -63,6 +80,7 @@ public class Curl
} }
final boolean d = dump; final boolean d = dump;
final boolean v = verbose;
HttpExchange ex = new HttpExchange() HttpExchange ex = new HttpExchange()
{ {
AtomicBoolean counted=new AtomicBoolean(false); AtomicBoolean counted=new AtomicBoolean(false);
@ -105,7 +123,8 @@ public class Curl
super.onResponseContent(content); super.onResponseContent(content);
if (d) if (d)
System.out.print(content.toString()); System.out.print(content.toString());
System.err.println("got "+content.length()); if (v)
System.err.println("got "+content.length());
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -116,7 +135,8 @@ public class Curl
protected void onResponseHeader(Buffer name, Buffer value) throws IOException protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{ {
super.onResponseHeader(name,value); super.onResponseHeader(name,value);
System.err.println(name+": "+value); if (v)
System.err.println(name+": "+value);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -127,7 +147,8 @@ public class Curl
protected void onResponseHeaderComplete() throws IOException protected void onResponseHeaderComplete() throws IOException
{ {
super.onResponseHeaderComplete(); super.onResponseHeaderComplete();
System.err.println(); if (v)
System.err.println();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -138,7 +159,8 @@ public class Curl
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{ {
super.onResponseStatus(version,status,reason); super.onResponseStatus(version,status,reason);
System.err.println(version+" "+status+" "+reason); if (v)
System.err.println(version+" "+status+" "+reason);
} }
}; };

View File

@ -0,0 +1,211 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/* ------------------------------------------------------------ */
/**
*/
public class Siege
{
private static final class ConcurrentExchange extends HttpExchange
{
private final long _start=System.currentTimeMillis();
private final HttpClient _client;
private final CountDownLatch _latch;
volatile int _status;
volatile int _count;
volatile long _bytes;
final List<String> _uris;
final int _repeats;
int _u;
int _r;
AtomicBoolean counted=new AtomicBoolean(false);
public ConcurrentExchange(HttpClient client,CountDownLatch latch, List<String> uris, int repeats)
{
_client = client;
_latch = latch;
_uris = uris;
_repeats = repeats;
}
@Override
protected void onConnectionFailed(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onConnectionFailed(ex);
}
@Override
protected void onException(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onException(ex);
}
@Override
protected void onExpire()
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onExpire();
}
@Override
protected void onResponseComplete() throws IOException
{
if (_status==200)
_count++;
if (!next() && !counted.getAndSet(true))
{
_latch.countDown();
long duration=System.currentTimeMillis()-_start;
System.err.printf("Got %d/%d with %dB in %dms %d%n",_count,_uris.size()*_repeats,_bytes,duration,_latch.getCount());
}
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseContent(Buffer content) throws IOException
{
_bytes+=content.length();
super.onResponseContent(content);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer)
*/
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
super.onResponseHeader(name,value);
if ("Set-Cookie".equalsIgnoreCase(name.toString()))
{
String v=value.toString();
int c = v.indexOf(';');
if (c>=0)
v=v.substring(0,c);
addRequestHeader("Cookie",v);
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete()
*/
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer)
*/
@Override
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
_status=status;
super.onResponseStatus(version,status,reason);
}
public boolean next()
{
if (_u>=_uris.size())
{
_u=0;
_r++;
if (_r>=_repeats)
return false;
}
String uri=_uris.get(_u++);
reset();
setMethod(HttpMethods.GET);
setURL(uri);
try
{
_client.send(this);
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
}
public static void main(String[] args)
throws Exception
{
if (args.length==0)
args=new String[]
{ "-c", "2", "-r", "2", "http://localhost:8080/dump", "http://localhost:8080/d.txt"};
int concurrent=1;
int repeats=1;
final List<String> uris = new ArrayList<String>();
for (int i=0; i<args.length; i++)
{
String arg=args[i];
if ("-c".equals(arg))
{
concurrent=Integer.parseInt(args[++i]);
continue;
}
if ("-r".equals(arg))
{
repeats=Integer.parseInt(args[++i]);
continue;
}
uris.add(arg);
}
QueuedThreadPool pool = new QueuedThreadPool();
pool.setMaxThreads(500);
pool.setDaemon(true);
HttpClient client = new HttpClient();
client.setThreadPool(pool);
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setIdleTimeout(30000);
client.setConnectTimeout(30000);
client.setMaxConnectionsPerAddress(concurrent*2);
client.start();
final CountDownLatch latch = new CountDownLatch(concurrent);
for (int i=0;i<concurrent;i++)
{
ConcurrentExchange ex = new ConcurrentExchange(client,latch,uris,repeats);
if (!ex.next())
latch.countDown();
}
latch.await();
client.stop();
pool.stop();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -162,6 +162,8 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
// we are not interested in further selecting // we are not interested in further selecting
_key.interestOps(0); _key.interestOps(0);
if (!_dispatched)
updateKey();
return; return;
} }

View File

@ -444,7 +444,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// Stopped concurrently ? // Stopped concurrently ?
if (selector == null) if (selector == null)
return; return;
// Make any key changes required // Make any key changes required
Object change; Object change;
int changes=_changes.size(); int changes=_changes.size();
@ -585,15 +585,6 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// Log and dump some status // Log and dump some status
_paused=true; _paused=true;
LOG.warn("Selector {} is too busy, pausing!",this); LOG.warn("Selector {} is too busy, pausing!",this);
final SelectSet set = this;
SelectorManager.this.dispatch(
new Runnable(){
public void run()
{
System.err.println(set+":\n"+set.dump());
}
public String toString() {return "Dump-"+super.toString();}
});
} }
} }
} }
@ -991,6 +982,16 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
dumpto.add(key.attachment()+" - - "); dumpto.add(key.attachment()+" - - ");
} }
} }
/* ------------------------------------------------------------ */
public String toString()
{
String s=super.toString()+" "+SelectorManager.this.getState();
Selector selector=_selector;
if (selector!=null && selector.isOpen())
s+=",k="+selector.keys().size()+",s="+selector.selectedKeys().size();
return s;
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -16,7 +16,6 @@ package org.eclipse.jetty.io.nio;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -236,9 +235,23 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void onClose() public void onClose()
{ {
} }
/* ------------------------------------------------------------ */
@Override
public void onIdleExpired()
{
try
{
_sslEndPoint.shutdownOutput();
}
catch (IOException e)
{
LOG.warn(e);
super.onIdleExpired();
}
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void onInputShutdown() throws IOException public void onInputShutdown() throws IOException
{ {
@ -586,6 +599,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
_engine.closeOutbound(); _engine.closeOutbound();
_oshut=true; _oshut=true;
} }
flush();
} }
public boolean isOutputShutdown() public boolean isOutputShutdown()
@ -786,14 +800,14 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
Buffer i; Buffer i;
Buffer o; Buffer o;
Buffer u; Buffer u;
synchronized(SslConnection.this) synchronized(SslConnection.this)
{ {
i=_inbound; i=_inbound;
o=_outbound; o=_outbound;
u=_unwrapBuf; u=_unwrapBuf;
} }
return "SSL:"+_endp+" "+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length()+(_oshut?" oshut":"")); return "SSL:"+_endp+" "+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length()+(_ishut?" ishut":"")+(_oshut?" oshut":""));
} }
} }

View File

@ -42,6 +42,7 @@ import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
@ -148,7 +149,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
_uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET); _uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
_connector = connector; _connector = connector;
HttpBuffers ab = (HttpBuffers)_connector; HttpBuffers ab = (HttpBuffers)_connector;
_parser = new HttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler()); _parser = newHttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler());
_requestFields = new HttpFields(); _requestFields = new HttpFields();
_responseFields = new HttpFields(server.getMaxCookieVersion()); _responseFields = new HttpFields(server.getMaxCookieVersion());
_request = new Request(this); _request = new Request(this);
@ -163,7 +164,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
Parser parser, Generator generator, Request request) Parser parser, Generator generator, Request request)
{ {
super(endpoint); super(endpoint);
_uri = URIUtil.__CHARSET.equals(StringUtil.__UTF8)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET); _uri = URIUtil.__CHARSET.equals(StringUtil.__UTF8)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
_connector = connector; _connector = connector;
_parser = parser; _parser = parser;
@ -176,6 +177,11 @@ public abstract class AbstractHttpConnection extends AbstractConnection
_server = server; _server = server;
} }
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endpoint, HttpParser.EventHandler requestHandler)
{
return new HttpParser(requestBuffers, endpoint, requestHandler);
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return the parser used by this connection * @return the parser used by this connection
@ -193,13 +199,13 @@ public abstract class AbstractHttpConnection extends AbstractConnection
{ {
return _requests; return _requests;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public Server getServer() public Server getServer()
{ {
return _server; return _server;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return Returns the associatedObject. * @return Returns the associatedObject.
@ -385,11 +391,11 @@ public abstract class AbstractHttpConnection extends AbstractConnection
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void reset() public void reset()
{ {
_parser.reset(); _parser.reset();
_parser.returnBuffers(); // TODO maybe only on unhandle _parser.returnBuffers(); // TODO maybe only on unhandle
_requestFields.clear(); _requestFields.clear();
_request.recycle(); _request.recycle();
_generator.reset(); _generator.reset();
_generator.returnBuffers();// TODO maybe only on unhandle _generator.returnBuffers();// TODO maybe only on unhandle
_responseFields.clear(); _responseFields.clear();
_response.recycle(); _response.recycle();
@ -566,7 +572,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
} }
catch(RuntimeException e) catch(RuntimeException e)
{ {
LOG.warn("header full: "+e); LOG.warn("header full: " + e);
_response.reset(); _response.reset();
_generator.reset(); _generator.reset();
@ -672,7 +678,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
{ {
LOG.debug("closed {}",this); LOG.debug("closed {}",this);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public boolean isExpecting100Continues() public boolean isExpecting100Continues()
{ {
@ -717,7 +723,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
{ {
uri=uri.asImmutableBuffer(); uri=uri.asImmutableBuffer();
_host = false; _host = false;
_expect = false; _expect = false;
_expect100Continue=false; _expect100Continue=false;
@ -864,11 +870,11 @@ public abstract class AbstractHttpConnection extends AbstractConnection
_generator.setPersistent(true); _generator.setPersistent(true);
_parser.setPersistent(true); _parser.setPersistent(true);
} }
if (_server.getSendDateHeader()) if (_server.getSendDateHeader())
_generator.setDate(_request.getTimeStampBuffer()); _generator.setDate(_request.getTimeStampBuffer());
break; break;
case HttpVersions.HTTP_1_1_ORDINAL: case HttpVersions.HTTP_1_1_ORDINAL:
_generator.setHead(_head); _generator.setHead(_head);
@ -959,7 +965,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Bad request!: "+version+" "+status+" "+reason); LOG.debug("Bad request!: "+version+" "+status+" "+reason);
} }
} }
@ -1144,5 +1150,5 @@ public abstract class AbstractHttpConnection extends AbstractConnection
} }
} }
} }

View File

@ -161,7 +161,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended()) if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
{ {
// then no more can happen, so close. // then no more can happen, so close.
_endp.shutdownOutput(); _endp.close();
} }
} }

View File

@ -102,6 +102,7 @@ public class BlockingHttpConnection extends AbstractHttpConnection
// Reset the parser/generator // Reset the parser/generator
progress=true; progress=true;
reset(); reset();
_endp.flush();
// look for a switched connection instance? // look for a switched connection instance?
if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101) if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
@ -114,7 +115,7 @@ public class BlockingHttpConnection extends AbstractHttpConnection
// TODO Is this required? // TODO Is this required?
if (!_generator.isPersistent() && !_endp.isOutputShutdown()) if (!_generator.isPersistent() && !_endp.isOutputShutdown())
{ {
System.err.println("Safety net oshut!!!"); LOG.warn("Safety net oshut!!! Please open a bugzilla");
_endp.shutdownOutput(); _endp.shutdownOutput();
} }
} }

View File

@ -68,6 +68,8 @@ public class ShutdownHandler extends AbstractHandler
private final Server _server; private final Server _server;
private boolean _exitJvm = false; private boolean _exitJvm = false;
/** /**
* Creates a listener that lets the server be shut down remotely (but only from localhost). * Creates a listener that lets the server be shut down remotely (but only from localhost).
@ -110,18 +112,24 @@ public class ShutdownHandler extends AbstractHandler
LOG.info("Shutting down by request from " + getRemoteAddr(request)); LOG.info("Shutting down by request from " + getRemoteAddr(request));
try new Thread()
{ {
shutdownServer(); public void run ()
} {
catch (InterruptedException e) try
{ {
LOG.ignore(e); shutdownServer();
} }
catch (Exception e) catch (InterruptedException e)
{ {
throw new RuntimeException("Shutting down server",e); LOG.ignore(e);
} }
catch (Exception e)
{
throw new RuntimeException("Shutting down server",e);
}
}
}.start();
} }
private boolean requestFromLocalhost(HttpServletRequest request) private boolean requestFromLocalhost(HttpServletRequest request)

View File

@ -31,14 +31,11 @@ import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager; import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet; import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.server.AsyncHttpConnection; import org.eclipse.jetty.server.AsyncHttpConnection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ThreadPool; import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.thread.Timeout.Task;
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/** /**
@ -97,7 +94,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
{ {
server = _acceptChannel; server = _acceptChannel;
} }
if (server!=null && server.isOpen() && _manager.isStarted()) if (server!=null && server.isOpen() && _manager.isStarted())
{ {
SocketChannel channel = server.accept(); SocketChannel channel = server.accept();
@ -144,7 +141,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
{ {
return _manager; return _manager;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public synchronized Object getConnection() public synchronized Object getConnection()
{ {
@ -297,7 +294,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
protected AsyncConnection newConnection(SocketChannel channel,final AsyncEndPoint endpoint) protected AsyncConnection newConnection(SocketChannel channel,final AsyncEndPoint endpoint)
{ {
return new SelectChannelHttpConnection(SelectChannelConnector.this,endpoint,getServer()); return new AsyncHttpConnection(SelectChannelConnector.this,endpoint,getServer());
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -310,24 +307,9 @@ public class SelectChannelConnector extends AbstractNIOConnector
channel=_acceptChannel; channel=_acceptChannel;
} }
if (channel==null) if (channel==null)
AggregateLifeCycle.dump(out,indent,Arrays.asList(new Object[]{null,"CLOSED",_manager})); AggregateLifeCycle.dump(out,indent,Arrays.asList(null,"CLOSED",_manager));
else else
AggregateLifeCycle.dump(out,indent,Arrays.asList(new Object[]{channel,channel.isOpen()?"OPEN":"CLOSED",_manager})); AggregateLifeCycle.dump(out,indent,Arrays.asList(channel,channel.isOpen()?"OPEN":"CLOSED",_manager));
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private class SelectChannelHttpConnection extends AsyncHttpConnection
{
private final AsyncEndPoint _endpoint;
private SelectChannelHttpConnection(Connector connector, EndPoint endpoint, Server server)
{
super(connector,endpoint,server);
_endpoint=null;
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -14,16 +14,12 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.Buffers;
@ -33,10 +29,7 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.io.nio.SslConnection; import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.server.AsyncHttpConnection;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -102,7 +95,7 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
SslConnection.SslEndPoint sslEndpoint=(SslConnection.SslEndPoint)endpoint; SslConnection.SslEndPoint sslEndpoint=(SslConnection.SslEndPoint)endpoint;
SSLEngine sslEngine=sslEndpoint.getSslEngine(); SSLEngine sslEngine=sslEndpoint.getSslEngine();
SSLSession sslSession=sslEngine.getSession(); SSLSession sslSession=sslEngine.getSession();
SslCertificates.customize(sslSession,endpoint,request); SslCertificates.customize(sslSession,endpoint,request);
} }
@ -541,13 +534,6 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
return integralPort==0||integralPort==request.getServerPort(); return integralPort==0||integralPort==request.getServerPort();
} }
/* ------------------------------------------------------------------------------- */
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
return super.newEndPoint(channel,selectSet,key);
}
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@Override @Override
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint) protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
@ -555,20 +541,28 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
try try
{ {
SSLEngine engine = createSSLEngine(channel); SSLEngine engine = createSSLEngine(channel);
SslConnection connection = newSslConnection(endpoint, engine);
SslConnection connection = new SslConnection(engine,endpoint); AsyncConnection delegate = newPlainConnection(channel, connection.getSslEndPoint());
AsyncConnection delegate = super.newConnection(channel,connection.getSslEndPoint());
connection.getSslEndPoint().setConnection(delegate); connection.getSslEndPoint().setConnection(delegate);
connection.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate()); connection.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate());
return connection; return connection;
} }
catch(IOException e) catch (IOException e)
{ {
throw new RuntimeIOException(e); throw new RuntimeIOException(e);
} }
} }
protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)
{
return super.newConnection(channel, endPoint);
}
protected SslConnection newSslConnection(AsyncEndPoint endpoint, SSLEngine engine)
{
return new SslConnection(engine, endpoint);
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param channel A channel which if passed is used as to extract remote * @param channel A channel which if passed is used as to extract remote
@ -589,7 +583,7 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
{ {
engine = _sslContextFactory.newSslEngine(); engine = _sslContextFactory.newSslEngine();
} }
engine.setUseClientMode(false); engine.setUseClientMode(false);
return engine; return engine;
} }

View File

@ -14,12 +14,18 @@ package org.eclipse.jetty.server.handler;
//======================================================================== //========================================================================
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
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.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mock; import org.mockito.Mock;
@ -48,8 +54,36 @@ public class ShutdownHandlerTest
public void shutdownServerWithCorrectTokenAndIPTest() throws Exception public void shutdownServerWithCorrectTokenAndIPTest() throws Exception
{ {
setDefaultExpectations(); setDefaultExpectations();
final CountDownLatch countDown = new CountDownLatch(1);
server.addLifeCycleListener(new AbstractLifeCycle.Listener ()
{
public void lifeCycleStarting(LifeCycle event)
{
}
public void lifeCycleStarted(LifeCycle event)
{
}
public void lifeCycleFailure(LifeCycle event, Throwable cause)
{
}
public void lifeCycleStopping(LifeCycle event)
{
}
public void lifeCycleStopped(LifeCycle event)
{
countDown.countDown();
}
});
shutdownHandler.handle("/shutdown",null,request,response); shutdownHandler.handle("/shutdown",null,request,response);
assertEquals("Server should be stopped","STOPPED",server.getState()); boolean stopped = countDown.await(1000, TimeUnit.MILLISECONDS); //wait up to 1 sec to stop
assertTrue("Server lifecycle stop listener called", stopped);
assertEquals("Server should be stopped","STOPPED",server.getState());
} }
@Test @Test

View File

@ -255,15 +255,8 @@ public class SslContextFactory extends AbstractLifeCycle
else else
{ {
// verify that keystore and truststore // verify that keystore and truststore
// parameters are set up correctly // parameters are set up correctly
try checkKeyStore();
{
checkKeyStore();
}
catch(IllegalStateException e)
{
LOG.ignore(e);
}
KeyStore keyStore = loadKeyStore(); KeyStore keyStore = loadKeyStore();
KeyStore trustStore = loadTrustStore(); KeyStore trustStore = loadTrustStore();
@ -1158,13 +1151,17 @@ public class SslContextFactory extends AbstractLifeCycle
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Check KetyStore Configuration. Ensures that if keystore has been * Check KeyStore Configuration. Ensures that if keystore has been
* configured but there's no truststore, that keystore is * configured but there's no truststore, that keystore is
* used as truststore. * used as truststore.
* @throws IllegalStateException if SslContextFactory configuration can't be used. * @throws IllegalStateException if SslContextFactory configuration can't be used.
*/ */
public void checkKeyStore() public void checkKeyStore()
{ {
if (_context != null)
return; //nothing to check if using preconfigured context
if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null) if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
throw new IllegalStateException("SSL doesn't have a valid keystore"); throw new IllegalStateException("SSL doesn't have a valid keystore");

View File

@ -160,4 +160,25 @@ public class SslContextFactoryTest
{ {
} }
} }
@Test
public void testNoKeyConfig() throws Exception
{
SslContextFactory cf = new SslContextFactory();
try
{
((StdErrLog)Log.getLogger(AbstractLifeCycle.class)).setHideStacks(true);
cf.setTrustStore("/foo");
cf.start();
Assert.fail();
}
catch (IllegalStateException e)
{
}
catch (Exception e)
{
Assert.fail("Unexpected exception");
}
}
} }