#!/bin/sh
+ set -e
JETTY=C:/jars/jetty-distribution-9.1.0.RC0/org.eclipse.jetty.project
-pushd ../lib/jetty/org/eclipse/jetty
+pushd ../../lib/jetty/org/eclipse/jetty
rm -fR *
pushd $JETTY
- git checkout refs/tags/jetty-9.2.1.v20140609
+ git checkout refs/tags/jetty-9.2.16.v20160407
popd
//
// ========================================================================
- // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+ // Copyright (c) 1995-2016 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
private static final ByteBuffer __FILL_CALLED_FLUSH= BufferUtil.allocate(0);
private static final ByteBuffer __FLUSH_CALLED_FILL= BufferUtil.allocate(0);
private final ByteBufferPool _bufferPool;
- private final SSLEngine _sslEngine;
+ private SSLEngine _sslEngine;
+ private final SslReconfigurator _sslFactory;
private final DecryptedEndPoint _decryptedEndPoint;
private ByteBuffer _decryptedInput;
private ByteBuffer _encryptedInput;
private boolean _renegotiationAllowed;
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
+ {
+ this(byteBufferPool, executor, endPoint, sslEngine, null);
+ }
+ public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine, SslReconfigurator fact)
{
// This connection does not execute calls to onfillable, so they will be called by the selector thread.
// onfillable does not block and will only wakeup another thread to do the actual reading and handling.
super(endPoint, executor, !EXECUTE_ONFILLABLE);
this._bufferPool = byteBufferPool;
this._sslEngine = sslEngine;
+ this._sslFactory = fact;
this._decryptedEndPoint = newDecryptedEndPoint();
}
private boolean _cannotAcceptMoreAppDataToFlush;
private boolean _handshaken;
private boolean _underFlown;
+ private boolean _peeking = _sslFactory != null;
private final Callback _writeCallback = new Callback()
{
{
@Override
public void succeeded()
- {
+ {
}
@Override
getFillInterest().onFail(x);
getWriteFlusher().onFail(x);
}
-
+
},x);
}
};
// all data could be wrapped. So either we need to write some encrypted data,
// OR if we are handshaking we need to read some encrypted data OR
// if neither then we should just try the flush again.
- boolean flush = false;
+ boolean try_again = false;
synchronized (DecryptedEndPoint.this)
{
if (DEBUG)
}
else
{
- flush = true;
+ // We can get here because the WriteFlusher might not see progress
+ // when it has just flushed the encrypted data, but not consumed anymore
+ // of the application buffers. This is mostly avoided by another iteration
+ // within DecryptedEndPoint flush(), but I cannot convince myself that
+ // this is never ever the case.
+ try_again = true;
}
}
- if (flush)
+
+
+ if (try_again)
{
// If the output is closed,
if (isOutputShutdown())
else
{
// try to flush what is pending
- getWriteFlusher().completeWrite();
+ // because this is a special case (see above) we could probably
+ // avoid the dispatch, but best to be sure
+ getExecutor().execute(_runCompletWrite);
}
}
}
// We will need a network buffer
if (_encryptedInput == null)
_encryptedInput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
- else
+ else if(!_peeking)
BufferUtil.compact(_encryptedInput);
// We also need an app buffer, but can use the passed buffer if it is big enough
// Let's unwrap even if we have no net data because in that
// case we want to fall through to the handshake handling
int pos = BufferUtil.flipToFill(app_in);
- SSLEngineResult unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
- BufferUtil.flipToFlush(app_in, pos);
+ SSLEngineResult unwrapResult;
+ try
+ {
+ unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
+ }
+ finally
+ {
+ BufferUtil.flipToFlush(app_in, pos);
+ }
if (DEBUG)
LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
HandshakeStatus unwrapHandshakeStatus = unwrapResult.getHandshakeStatus();
Status unwrapResultStatus = unwrapResult.getStatus();
- _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW;
+ // Extra check on unwrapResultStatus == OK with zero length buffer is due
+ // to SSL client on android (see bug #454773)
+ _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW || unwrapResultStatus == Status.OK && unwrapResult.bytesConsumed()==0 && unwrapResult.bytesProduced()==0;
if (_underFlown)
{
// or shutting down the output.
return -1;
}
+ case NEED_UNWRAP:
+ {
+ // We expected to read more, but we got closed.
+ // Return -1 to indicate to the application to drive the close.
+ return -1;
+ }
default:
{
throw new IllegalStateException();
case NEED_TASK:
{
_sslEngine.getDelegatedTask().run();
+ if(_peeking)
+ {
+ _sslEngine = _sslFactory.restartSSL(_sslEngine.getHandshakeSession());
+ _encryptedInput.position(0);
+ _peeking = false;
+ continue decryption;
+ }
continue;
}
case NEED_WRAP:
}
catch (Exception e)
{
- getEndPoint().close();
+ close();
throw e;
}
finally
// We call sslEngine.wrap to try to take bytes from appOut buffers and encrypt them into the _netOut buffer
BufferUtil.compact(_encryptedOutput);
int pos = BufferUtil.flipToFill(_encryptedOutput);
- SSLEngineResult wrapResult = _sslEngine.wrap(appOuts, _encryptedOutput);
+ SSLEngineResult wrapResult;
+ try
+ {
+ wrapResult=_sslEngine.wrap(appOuts, _encryptedOutput);
+ }
+ finally
+ {
+ BufferUtil.flipToFlush(_encryptedOutput, pos);
+ }
+
if (DEBUG)
LOG.debug("{} wrap {}", SslConnection.this, wrapResult);
- BufferUtil.flipToFlush(_encryptedOutput, pos);
if (wrapResult.bytesConsumed()>0)
consumed+=wrapResult.bytesConsumed();
+ Status wrapResultStatus = wrapResult.getStatus();
boolean allConsumed=true;
- // clear empty buffers to prevent position creeping up the buffer
for (ByteBuffer b : appOuts)
- {
- if (BufferUtil.isEmpty(b))
- BufferUtil.clear(b);
- else
+ if (BufferUtil.hasContent(b))
allConsumed=false;
- }
-
- Status wrapResultStatus = wrapResult.getStatus();
// and deal with the results returned from the sslEngineWrap
switch (wrapResultStatus)
{
if (DEBUG)
LOG.debug("{} renegotiation denied", SslConnection.this);
- shutdownOutput();
+ getEndPoint().shutdownOutput();
return allConsumed;
}
// if we have net bytes, let's try to flush them
if (BufferUtil.hasContent(_encryptedOutput))
- getEndPoint().flush(_encryptedOutput);
+ if (!getEndPoint().flush(_encryptedOutput))
+ getEndPoint().flush(_encryptedOutput); // one retry
// But we also might have more to do for the handshaking state.
switch (handshakeStatus)
{
case NOT_HANDSHAKING:
- // Return with the number of bytes consumed (which may be 0)
+ // If we have not consumed all and had just finished handshaking, then we may
+ // have just flushed the last handshake in the encrypted buffers, so we should
+ // try again.
+ if (!allConsumed && wrapResult.getHandshakeStatus()==HandshakeStatus.FINISHED && BufferUtil.isEmpty(_encryptedOutput))
+ continue;
+
+ // Return true if we consumed all the bytes and encrypted are all flushed
return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
case NEED_TASK:
}
}
}
- catch (Exception e)
- {
- getEndPoint().close();
- throw e;
- }
finally
{
if (DEBUG)
//
// ========================================================================
- // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+ // Copyright (c) 1995-2016 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
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection;
+import org.eclipse.jetty.io.ssl.SslReconfigurator;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-public class SslConnectionFactory extends AbstractConnectionFactory
+public class SslConnectionFactory extends AbstractConnectionFactory implements SslReconfigurator
{
private final SslContextFactory _sslContextFactory;
private final String _nextProtocol;
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
{
- return new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endPoint, engine);
+ return new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endPoint, engine, shouldRestartSSL()?this:null);
+ }
+
+ public boolean shouldRestartSSL(){
+ return false;
+ }
+
+ public SSLEngine restartSSL(SSLSession sslSession){
+ throw new UnsupportedOperationException();
}
@Override
//
// ========================================================================
- // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+ // Copyright (c) 1995-2016 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
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
- import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.ClassLoaderDump;
- import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
public class ContextHandler extends ScopedHandler implements Attributes, Graceful
{
public final static int SERVLET_MAJOR_VERSION=3;
- public final static int SERVLET_MINOR_VERSION=0;
- public static final Class[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
+ public final static int SERVLET_MINOR_VERSION=1;
+ public static final Class<?>[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
ServletContextAttributeListener.class,
ServletRequestListener.class,
ServletRequestAttributeListener.class};
/*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
- @SuppressWarnings("rawtypes")
- public Enumeration getInitParameterNames()
+ public Enumeration<String> getInitParameterNames()
{
return Collections.enumeration(_initParams.keySet());
}
_managedAttributes = new HashMap<String, Object>();
String[] attributes = managedAttributes.split(",");
for (String attribute : attributes)
- _managedAttributes.put(attribute,null);
+ {
+ _managedAttributes.put(attribute.trim(),null);
+ }
Enumeration<String> e = _scontext.getAttributeNames();
while (e.hasMoreElements())
/* ------------------------------------------------------------ */
protected void callContextInitialized (ServletContextListener l, ServletContextEvent e)
{
- LOG.debug("contextInitialized: {}->{}",e,l);
+ if (LOG.isDebugEnabled())
+ LOG.debug("contextInitialized: {}->{}",e,l);
l.contextInitialized(e);
}
/* ------------------------------------------------------------ */
protected void callContextDestroyed (ServletContextListener l, ServletContextEvent e)
{
- LOG.debug("contextDestroyed: {}->{}",e,l);
+ if (LOG.isDebugEnabled())
+ LOG.debug("contextDestroyed: {}->{}",e,l);
l.contextDestroyed(e);
}
_scontext.clearAttributes();
}
- /* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
- public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
+ public boolean checkVirtualHost(final Request baseRequest)
{
- DispatcherType dispatch = baseRequest.getDispatcherType();
-
- switch (_availability)
- {
- case SHUTDOWN:
- case UNAVAILABLE:
- baseRequest.setHandled(true);
- response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- return false;
- default:
- if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
- return false;
- }
-
- // Check the vhosts
if (_vhosts != null && _vhosts.length > 0)
{
String vhost = normalizeHostname(baseRequest.getServerName());
if (!match || connectorName && !connectorMatch)
return false;
}
-
+ return true;
+ }
+
+ public boolean checkContextPath(String uri)
+ {
// Are we not the root context?
if (_contextPath.length() > 1)
{
// reject requests that are not for us
- if (!target.startsWith(_contextPath))
+ if (!uri.startsWith(_contextPath))
return false;
- if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/')
+ if (uri.length() > _contextPath.length() && uri.charAt(_contextPath.length()) != '/')
return false;
+ }
+ return true;
+ }
+
+ /* ------------------------------------------------------------ */
+ /*
+ * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
+ {
+ DispatcherType dispatch = baseRequest.getDispatcherType();
- // redirect null path infos
- if (!_allowNullPathInfo && _contextPath.length() == target.length())
- {
- // context request must end with /
+ // Check the vhosts
+ if (!checkVirtualHost(baseRequest))
+ return false;
+
+ if (!checkContextPath(target))
+ return false;
+
+ // Are we not the root context?
+ // redirect null path infos
+ if (!_allowNullPathInfo && _contextPath.length() == target.length() && _contextPath.length()>1)
+ {
+ // context request must end with /
+ baseRequest.setHandled(true);
+ if (baseRequest.getQueryString() != null)
+ response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
+ else
+ response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
+ return false;
+ }
+
+ switch (_availability)
+ {
+ case SHUTDOWN:
+ case UNAVAILABLE:
baseRequest.setHandled(true);
- if (baseRequest.getQueryString() != null)
- response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
- else
- response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return false;
- }
+ default:
+ if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
+ return false;
}
return true;
if (!_requestAttributeListeners.isEmpty())
{
- ListIterator<ServletRequestAttributeListener> iter = _requestAttributeListeners.listIterator(_requestAttributeListeners.size());
for (int i=_requestAttributeListeners.size();i-->0;)
baseRequest.removeEventListener(_requestAttributeListeners.get(i));
}
}
/* ------------------------------------------------------------ */
+ /**
+ * @param path
+ * @param resource
+ * @return True if the alias is OK
+ */
public boolean checkAlias(String path, Resource resource)
{
// Is the resource aliased?
- if (resource.getAlias() != null)
+ if (resource.getAlias() != null)
{
if (LOG.isDebugEnabled())
LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
matched_path = context_path;
}
- if (matched_path.equals(context_path))
+ if (matched_path != null && matched_path.equals(context_path))
contexts.add(ch);
}
}
/*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
- @SuppressWarnings("unchecked")
@Override
public Enumeration<String> getInitParameterNames()
{
try
{
- Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
+ @SuppressWarnings("unchecked")
+ Class<? extends EventListener> clazz = (Class<? extends EventListener>) (_classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className));
addListener(clazz);
}
catch (ClassNotFoundException e)
//classloader, or a parent of it
try
{
- Class reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
+ Class<?> reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
Method getCallerClass = reflect.getMethod("getCallerClass", Integer.TYPE);
- Class caller = (Class)getCallerClass.invoke(null, 2);
+ Class<?> caller = (Class<?>)getCallerClass.invoke(null, 2);
boolean ok = false;
ClassLoader callerLoader = caller.getClassLoader();
@Override
public String getServerInfo()
{
+ // NOTE: DO NOT CHANGE
+ // this is used by weld to detect Jetty
+ // implementation version
+ // See: https://github.com/weld/core/blob/master/environments/servlet/core/src/main/java/org/jboss/weld/environment/jetty/JettyContainer.java
+ // and its touch(ContainerContext) method
return "jetty/" + Server.getVersion();
}