Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project
This commit is contained in:
commit
c596add40c
|
@ -1,22 +1,19 @@
|
|||
package org.eclipse.jetty.annotations.resources;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser;
|
||||
import org.eclipse.jetty.annotations.ClassNameResolver;
|
||||
import org.eclipse.jetty.annotations.ResourceAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.ResourcesAnnotationHandler;
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -24,24 +21,39 @@ import static org.junit.Assert.assertNotNull;
|
|||
|
||||
public class TestResourceAnnotations
|
||||
{
|
||||
Object objA=new Integer(1000);
|
||||
Object objB=new Integer(2000);
|
||||
private Server server;
|
||||
private WebAppContext wac;
|
||||
private InjectionCollection injections;
|
||||
private Context comp;
|
||||
private Context env;
|
||||
private Object objA = 1000;
|
||||
private Object objB = 2000;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
InitialContext ic = new InitialContext();
|
||||
comp = (Context)ic.lookup("java:comp");
|
||||
env = comp.createSubcontext("env");
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
comp.destroySubcontext("env");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
|
||||
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
|
||||
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
|
||||
|
||||
AnnotationIntrospector parser = new AnnotationIntrospector();
|
||||
ResourceAnnotationHandler handler = new ResourceAnnotationHandler(wac);
|
||||
|
@ -116,25 +128,14 @@ public class TestResourceAnnotations
|
|||
f = ResourceA.class.getDeclaredField("n");
|
||||
f.setAccessible(true);
|
||||
assertEquals(objB, f.get(binst));
|
||||
|
||||
comp.destroySubcontext("env");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testResourcesAnnotation ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
|
||||
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
|
||||
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
|
||||
|
||||
AnnotationIntrospector introspector = new AnnotationIntrospector();
|
||||
ResourcesAnnotationHandler handler = new ResourcesAnnotationHandler(wac);
|
||||
|
|
|
@ -13,11 +13,15 @@
|
|||
|
||||
package org.eclipse.jetty.plus.jndi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.Binding;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.RefAddr;
|
||||
import javax.naming.Reference;
|
||||
|
@ -25,6 +29,7 @@ import javax.naming.Referenceable;
|
|||
import javax.naming.StringRefAddr;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -125,6 +130,35 @@ public class TestNamingEntries
|
|||
public void init()
|
||||
{
|
||||
this.someObject = new SomeObject(4);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* after each test we should scrape out any lingering bindings to prevent cross test pollution
|
||||
* as observed when running java 7
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@After
|
||||
public void after() throws Exception
|
||||
{
|
||||
InitialContext icontext = new InitialContext();
|
||||
|
||||
NamingEnumeration<Binding> bindings = icontext.listBindings("");
|
||||
List<String> names = new ArrayList<String>();
|
||||
while (bindings.hasMore())
|
||||
{
|
||||
Binding bd = (Binding)bindings.next();
|
||||
names.add(bd.getName());
|
||||
}
|
||||
|
||||
for (String name : names)
|
||||
{
|
||||
icontext.unbind(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -199,6 +233,7 @@ public class TestNamingEntries
|
|||
|
||||
ne = NamingEntryUtil.lookupNamingEntry(new ScopeB(), "resourceB");
|
||||
assertNull(ne);
|
||||
testLink();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -13,7 +10,6 @@ import java.net.Socket;
|
|||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
@ -31,6 +27,9 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
|
@ -188,7 +187,7 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
|
|||
|
||||
public X509Certificate[] getAcceptedIssuers()
|
||||
{
|
||||
return null;
|
||||
return new X509Certificate[]{};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.io.OutputStream;
|
|||
import java.net.Socket;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
@ -36,7 +35,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -53,17 +51,15 @@ public class SSLCloseTest extends TestCase
|
|||
{
|
||||
public X509Certificate[] getAcceptedIssuers()
|
||||
{
|
||||
return null;
|
||||
return new X509Certificate[]{};
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -67,12 +68,17 @@ public class GzipFilter extends UserAgentFilter
|
|||
protected Set<String> _mimeTypes;
|
||||
protected int _bufferSize=8192;
|
||||
protected int _minGzipSize=256;
|
||||
protected Set<String> _excluded;
|
||||
protected Set<String> _excludedAgents;
|
||||
protected Set<Pattern> _excludedAgentPatterns;
|
||||
protected Set<String> _excludedPaths;
|
||||
protected Set<Pattern> _excludedPathPatterns;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#init(javax.servlet.FilterConfig)
|
||||
*/
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
super.init(filterConfig);
|
||||
|
@ -93,14 +99,40 @@ public class GzipFilter extends UserAgentFilter
|
|||
while (tok.hasMoreTokens())
|
||||
_mimeTypes.add(tok.nextToken());
|
||||
}
|
||||
|
||||
tmp=filterConfig.getInitParameter("excludedAgents");
|
||||
if (tmp!=null)
|
||||
{
|
||||
_excluded=new HashSet<String>();
|
||||
_excludedAgents=new HashSet<String>();
|
||||
StringTokenizer tok = new StringTokenizer(tmp,",",false);
|
||||
while (tok.hasMoreTokens())
|
||||
_excluded.add(tok.nextToken());
|
||||
_excludedAgents.add(tok.nextToken());
|
||||
}
|
||||
|
||||
tmp=filterConfig.getInitParameter("excludeAgentPatterns");
|
||||
if (tmp!=null)
|
||||
{
|
||||
_excludedAgentPatterns=new HashSet<Pattern>();
|
||||
StringTokenizer tok = new StringTokenizer(tmp,",",false);
|
||||
while (tok.hasMoreTokens())
|
||||
_excludedAgentPatterns.add(Pattern.compile(tok.nextToken()));
|
||||
}
|
||||
|
||||
tmp=filterConfig.getInitParameter("excludePaths");
|
||||
if (tmp!=null)
|
||||
{
|
||||
_excludedPaths=new HashSet<String>();
|
||||
StringTokenizer tok = new StringTokenizer(tmp,",",false);
|
||||
while (tok.hasMoreTokens())
|
||||
_excludedPaths.add(tok.nextToken());
|
||||
}
|
||||
|
||||
tmp=filterConfig.getInitParameter("excludePathPatterns");
|
||||
if (tmp!=null)
|
||||
{
|
||||
_excludedPathPatterns=new HashSet<Pattern>();
|
||||
StringTokenizer tok = new StringTokenizer(tmp,",",false);
|
||||
while (tok.hasMoreTokens())
|
||||
_excludedPathPatterns.add(Pattern.compile(tok.nextToken()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +140,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
@ -116,6 +149,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
|
@ -126,14 +160,17 @@ public class GzipFilter extends UserAgentFilter
|
|||
if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
|
||||
&& !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
|
||||
{
|
||||
if (_excluded!=null)
|
||||
String ua = getUserAgent(request);
|
||||
if (isExcludedAgent(ua))
|
||||
{
|
||||
String ua=getUserAgent(request);
|
||||
if (_excluded.contains(ua))
|
||||
{
|
||||
super.doFilter(request,response,chain);
|
||||
return;
|
||||
}
|
||||
super.doFilter(request,response,chain);
|
||||
return;
|
||||
}
|
||||
String requestURI = request.getRequestURI();
|
||||
if (isExcludedPath(requestURI))
|
||||
{
|
||||
super.doFilter(request,response,chain);
|
||||
return;
|
||||
}
|
||||
|
||||
final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
|
||||
|
@ -182,6 +219,63 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the UserAgent is excluded
|
||||
*
|
||||
* @param ua
|
||||
* the user agent
|
||||
* @return boolean true if excluded
|
||||
*/
|
||||
private boolean isExcludedAgent(String ua)
|
||||
{
|
||||
if (ua == null)
|
||||
return false;
|
||||
|
||||
if (_excludedAgents != null)
|
||||
{
|
||||
if (_excludedAgents.contains(ua))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (_excludedAgentPatterns != null)
|
||||
{
|
||||
for (Pattern pattern : _excludedAgentPatterns)
|
||||
{
|
||||
if (pattern.matcher(ua).matches())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the Path is excluded
|
||||
*
|
||||
* @param ua
|
||||
* the request uri
|
||||
* @return boolean true if excluded
|
||||
*/
|
||||
private boolean isExcludedPath(String requestURI)
|
||||
{
|
||||
if (requestURI == null)
|
||||
return false;
|
||||
if (_excludedPathPatterns != null)
|
||||
{
|
||||
for (Pattern pattern : _excludedPathPatterns)
|
||||
{
|
||||
if (pattern.matcher(requestURI).matches())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace ResponseWrapper implementation.
|
||||
*
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.util.Map;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -52,7 +51,7 @@ public class UserAgentFilter implements Filter
|
|||
{
|
||||
private static final String __defaultPattern = "(?:Mozilla[^\\(]*\\(compatible;\\s*+([^;]*);.*)|(?:.*?([^\\s]+/[^\\s]+).*)";
|
||||
private Pattern _pattern = Pattern.compile(__defaultPattern);
|
||||
private Map _agentCache = new ConcurrentHashMap();
|
||||
private Map<String, String> _agentCache = new ConcurrentHashMap<String, String>();
|
||||
private int _agentCacheSize=1024;
|
||||
private String _attribute;
|
||||
|
||||
|
@ -112,37 +111,42 @@ public class UserAgentFilter implements Filter
|
|||
*/
|
||||
public String getUserAgent(String ua)
|
||||
{
|
||||
if (ua==null)
|
||||
if (ua == null)
|
||||
return null;
|
||||
|
||||
String tag = (String)_agentCache.get(ua);
|
||||
String tag = _agentCache.get(ua);
|
||||
|
||||
|
||||
if (tag==null)
|
||||
if (tag == null)
|
||||
{
|
||||
Matcher matcher=_pattern.matcher(ua);
|
||||
if (matcher.matches())
|
||||
if (_pattern != null)
|
||||
{
|
||||
if(matcher.groupCount()>0)
|
||||
Matcher matcher = _pattern.matcher(ua);
|
||||
if (matcher.matches())
|
||||
{
|
||||
for (int g=1;g<=matcher.groupCount();g++)
|
||||
if (matcher.groupCount() > 0)
|
||||
{
|
||||
String group=matcher.group(g);
|
||||
if (group!=null)
|
||||
tag=tag==null?group:(tag+group);
|
||||
for (int g = 1; g <= matcher.groupCount(); g++)
|
||||
{
|
||||
String group = matcher.group(g);
|
||||
if (group != null)
|
||||
tag = tag == null ? group : tag + group;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tag = matcher.group();
|
||||
}
|
||||
}
|
||||
else
|
||||
tag=matcher.group();
|
||||
}
|
||||
else
|
||||
tag=ua;
|
||||
|
||||
if (_agentCache.size()>=_agentCacheSize)
|
||||
_agentCache.clear();
|
||||
_agentCache.put(ua,tag);
|
||||
if (tag == null)
|
||||
tag = ua;
|
||||
|
||||
if (_agentCache.size() >= _agentCacheSize)
|
||||
_agentCache.clear();
|
||||
_agentCache.put(ua, tag);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,4 +38,9 @@ public class SessionException extends RuntimeException
|
|||
super(cause);
|
||||
this.sessionStatus = sessionStatus;
|
||||
}
|
||||
|
||||
public SessionStatus getSessionStatus()
|
||||
{
|
||||
return sessionStatus;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
|
||||
@Override
|
||||
public void syn(SynInfo synInfo, StreamFrameListener listener, long timeout, TimeUnit unit, final Handler<Stream> handler)
|
||||
public void syn(SynInfo synInfo, StreamFrameListener listener, long timeout, TimeUnit unit, Handler<Stream> handler)
|
||||
{
|
||||
// Synchronization is necessary.
|
||||
// SPEC v3, 2.3.1 requires that the stream creation be monotonically crescent
|
||||
|
@ -154,7 +154,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
{
|
||||
int streamId = streamIds.getAndAdd(2);
|
||||
SynStreamFrame synStream = new SynStreamFrame(version, synInfo.getFlags(), streamId, 0, synInfo.getPriority(), synInfo.getHeaders());
|
||||
final IStream stream = createStream(synStream, listener);
|
||||
IStream stream = createStream(synStream, listener);
|
||||
control(stream, synStream, timeout, unit, handler, stream);
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,11 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
else
|
||||
{
|
||||
RstStreamFrame frame = new RstStreamFrame(version, rstInfo.getStreamId(), rstInfo.getStreamStatus().getCode(version));
|
||||
int streamId = rstInfo.getStreamId();
|
||||
IStream stream = streams.get(streamId);
|
||||
if (stream != null)
|
||||
removeStream(stream);
|
||||
RstStreamFrame frame = new RstStreamFrame(version, streamId, rstInfo.getStreamStatus().getCode(version));
|
||||
control(null, frame, timeout, unit, handler, null);
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +211,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
|
||||
@Override
|
||||
public void ping(long timeout, TimeUnit unit, final Handler<PingInfo> handler)
|
||||
public void ping(long timeout, TimeUnit unit, Handler<PingInfo> handler)
|
||||
{
|
||||
int pingId = pingIds.getAndAdd(2);
|
||||
PingInfo pingInfo = new PingInfo(pingId);
|
||||
|
@ -217,20 +221,30 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
|
||||
@Override
|
||||
public Future<Void> goAway()
|
||||
{
|
||||
return goAway(SessionStatus.OK);
|
||||
}
|
||||
|
||||
private Future<Void> goAway(SessionStatus sessionStatus)
|
||||
{
|
||||
Promise<Void> result = new Promise<>();
|
||||
goAway(0, TimeUnit.MILLISECONDS, result);
|
||||
goAway(sessionStatus, 0, TimeUnit.MILLISECONDS, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void goAway(long timeout, TimeUnit unit, Handler<Void> handler)
|
||||
{
|
||||
goAway(SessionStatus.OK, timeout, unit, handler);
|
||||
}
|
||||
|
||||
private void goAway(SessionStatus sessionStatus, long timeout, TimeUnit unit, Handler<Void> handler)
|
||||
{
|
||||
if (goAwaySent.compareAndSet(false, true))
|
||||
{
|
||||
if (!goAwayReceived.get())
|
||||
{
|
||||
GoAwayFrame frame = new GoAwayFrame(version, lastStreamId.get(), SessionStatus.OK.getCode());
|
||||
GoAwayFrame frame = new GoAwayFrame(version, lastStreamId.get(), sessionStatus.getCode());
|
||||
control(null, frame, timeout, unit, handler, null);
|
||||
return;
|
||||
}
|
||||
|
@ -320,7 +334,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onDataFrame(final DataFrame frame, final ByteBuffer data)
|
||||
public void onDataFrame(DataFrame frame, ByteBuffer data)
|
||||
{
|
||||
notifyIdle(idleListener, false);
|
||||
try
|
||||
|
@ -334,7 +348,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
|
||||
int streamId = frame.getStreamId();
|
||||
final IStream stream = streams.get(streamId);
|
||||
IStream stream = streams.get(streamId);
|
||||
if (stream == null)
|
||||
{
|
||||
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
|
||||
|
@ -369,20 +383,21 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
@Override
|
||||
public void onStreamException(StreamException x)
|
||||
{
|
||||
logger.info("Caught stream exception", x);
|
||||
notifyOnException(listener, x);
|
||||
rst(new RstInfo(x.getStreamId(), x.getStreamStatus()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionException(SessionException x)
|
||||
{
|
||||
logger.info("Caught session exception", x);
|
||||
goAway();
|
||||
Throwable cause = x.getCause();
|
||||
notifyOnException(listener, cause == null ? x : cause);
|
||||
goAway(x.getSessionStatus());
|
||||
}
|
||||
|
||||
private void onSyn(final SynStreamFrame frame)
|
||||
private void onSyn(SynStreamFrame frame)
|
||||
{
|
||||
final IStream stream = newStream(frame);
|
||||
IStream stream = newStream(frame);
|
||||
logger.debug("Opening {}", stream);
|
||||
int streamId = frame.getStreamId();
|
||||
IStream existing = streams.putIfAbsent(streamId, stream);
|
||||
|
@ -480,10 +495,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
}
|
||||
|
||||
private void onReply(final SynReplyFrame frame)
|
||||
private void onReply(SynReplyFrame frame)
|
||||
{
|
||||
int streamId = frame.getStreamId();
|
||||
final IStream stream = streams.get(streamId);
|
||||
IStream stream = streams.get(streamId);
|
||||
if (stream == null)
|
||||
{
|
||||
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
|
||||
|
@ -503,11 +518,11 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
removeStream(stream);
|
||||
}
|
||||
|
||||
private void onRst(final RstStreamFrame frame)
|
||||
private void onRst(RstStreamFrame frame)
|
||||
{
|
||||
// TODO: implement logic to clean up unidirectional streams associated with this stream
|
||||
|
||||
final IStream stream = streams.get(frame.getStreamId());
|
||||
IStream stream = streams.get(frame.getStreamId());
|
||||
|
||||
if (stream != null)
|
||||
stream.process(frame);
|
||||
|
@ -520,7 +535,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
removeStream(stream);
|
||||
}
|
||||
|
||||
private void onSettings(final SettingsFrame frame)
|
||||
private void onSettings(SettingsFrame frame)
|
||||
{
|
||||
Settings.Setting windowSizeSetting = frame.getSettings().get(Settings.ID.INITIAL_WINDOW_SIZE);
|
||||
if (windowSizeSetting != null)
|
||||
|
@ -534,7 +549,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
flush();
|
||||
}
|
||||
|
||||
private void onPing(final PingFrame frame)
|
||||
private void onPing(PingFrame frame)
|
||||
{
|
||||
int pingId = frame.getPingId();
|
||||
if (pingId % 2 == pingIds.get() % 2)
|
||||
|
@ -549,7 +564,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
}
|
||||
|
||||
private void onGoAway(final GoAwayFrame frame)
|
||||
private void onGoAway(GoAwayFrame frame)
|
||||
{
|
||||
if (goAwayReceived.compareAndSet(false, true))
|
||||
{
|
||||
|
@ -563,10 +578,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
}
|
||||
|
||||
private void onHeaders(final HeadersFrame frame)
|
||||
private void onHeaders(HeadersFrame frame)
|
||||
{
|
||||
int streamId = frame.getStreamId();
|
||||
final IStream stream = streams.get(streamId);
|
||||
IStream stream = streams.get(streamId);
|
||||
if (stream == null)
|
||||
{
|
||||
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
|
||||
|
@ -601,6 +616,22 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
controller.close(false);
|
||||
}
|
||||
|
||||
private void notifyOnException(SessionFrameListener listener, Throwable x)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
logger.debug("Invoking callback with {} on listener {}", x, listener);
|
||||
listener.onException(x);
|
||||
}
|
||||
}
|
||||
catch (Exception xx)
|
||||
{
|
||||
logger.info("Exception while notifying listener " + listener, xx);
|
||||
}
|
||||
}
|
||||
|
||||
private StreamFrameListener notifyOnSyn(SessionFrameListener listener, Stream stream, SynInfo synInfo)
|
||||
{
|
||||
try
|
||||
|
@ -650,7 +681,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
}
|
||||
|
||||
private void notifyOnPing(SessionFrameListener listener, final PingInfo pingInfo)
|
||||
private void notifyOnPing(SessionFrameListener listener, PingInfo pingInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -683,7 +714,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
|
||||
@Override
|
||||
public <C> void control(IStream stream, ControlFrame frame, long timeout, TimeUnit unit, final Handler<C> handler, C context)
|
||||
public <C> void control(IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Handler<C> handler, C context)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -705,7 +736,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
|
||||
flush();
|
||||
}
|
||||
catch (final Throwable x)
|
||||
catch (Throwable x)
|
||||
{
|
||||
notifyHandlerFailed(handler, x);
|
||||
}
|
||||
|
@ -738,7 +769,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
flush();
|
||||
}
|
||||
|
||||
private void execute(final Runnable task)
|
||||
private void execute(Runnable task)
|
||||
{
|
||||
threadPool.execute(task);
|
||||
}
|
||||
|
@ -813,7 +844,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
throw new SPDYException(x);
|
||||
}
|
||||
|
||||
protected void write(final ByteBuffer buffer, Handler<FrameBytes> handler, FrameBytes frameBytes)
|
||||
protected void write(ByteBuffer buffer, Handler<FrameBytes> handler, FrameBytes frameBytes)
|
||||
{
|
||||
if (controller != null)
|
||||
controller.write(buffer, handler, frameBytes);
|
||||
|
@ -828,7 +859,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
// starvation (for the last frames sent) and stack overflow.
|
||||
// Therefore every some invocation, we dispatch to a new thread
|
||||
Integer invocations = handlerInvocations.get();
|
||||
if (invocations >= 8)
|
||||
if (invocations >= 4)
|
||||
{
|
||||
execute(new Runnable()
|
||||
{
|
||||
|
@ -850,7 +881,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
finally
|
||||
{
|
||||
handlerInvocations.set(invocations - 1);
|
||||
handlerInvocations.set(invocations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -910,7 +941,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
StandardSession.this.complete(handler, context);
|
||||
}
|
||||
|
||||
protected void fail(final Throwable x)
|
||||
protected void fail(Throwable x)
|
||||
{
|
||||
notifyHandlerFailed(handler, x);
|
||||
}
|
||||
|
|
|
@ -36,13 +36,6 @@ public class StreamException extends RuntimeException
|
|||
this.streamStatus = streamStatus;
|
||||
}
|
||||
|
||||
public StreamException(int streamId, StreamStatus streamStatus, Throwable x)
|
||||
{
|
||||
super(x);
|
||||
this.streamId = streamId;
|
||||
this.streamStatus = streamStatus;
|
||||
}
|
||||
|
||||
public int getStreamId()
|
||||
{
|
||||
return streamId;
|
||||
|
|
|
@ -18,6 +18,9 @@ package org.eclipse.jetty.spdy.api;
|
|||
|
||||
import java.util.EventListener;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>A {@link SessionFrameListener} is the passive counterpart of a {@link Session} and receives events happening
|
||||
* on a SPDY session.</p>
|
||||
|
@ -105,11 +108,22 @@ public interface SessionFrameListener extends EventListener
|
|||
*/
|
||||
public void onGoAway(Session session, GoAwayInfo goAwayInfo);
|
||||
|
||||
/**
|
||||
* <p>Callback invoked when an exception is thrown during the processing of an event on a
|
||||
* SPDY session.</p>
|
||||
* <p>Examples of such conditions are invalid frames received, corrupted headers compression state, etc.</p>
|
||||
*
|
||||
* @param x the exception that caused the event processing failure
|
||||
*/
|
||||
public void onException(Throwable x);
|
||||
|
||||
/**
|
||||
* <p>Empty implementation of {@link SessionFrameListener}</p>
|
||||
*/
|
||||
public static class Adapter implements SessionFrameListener
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(Adapter.class);
|
||||
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
|
@ -135,5 +149,11 @@ public interface SessionFrameListener extends EventListener
|
|||
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Throwable x)
|
||||
{
|
||||
logger.info("", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,27 +47,27 @@ public enum StreamStatus
|
|||
/**
|
||||
* <p>The stream status indicating an implementation error</p>
|
||||
*/
|
||||
INTERNAL_ERROR(6, 11),
|
||||
INTERNAL_ERROR(6, 6),
|
||||
/**
|
||||
* <p>The stream status indicating a flow control error</p>
|
||||
*/
|
||||
FLOW_CONTROL_ERROR(7, 6),
|
||||
FLOW_CONTROL_ERROR(7, 7),
|
||||
/**
|
||||
* <p>The stream status indicating a stream opened more than once</p>
|
||||
*/
|
||||
STREAM_IN_USE(-1, 7),
|
||||
STREAM_IN_USE(-1, 8),
|
||||
/**
|
||||
* <p>The stream status indicating data on a stream already closed</p>
|
||||
*/
|
||||
STREAM_ALREADY_CLOSED(-1, 8),
|
||||
STREAM_ALREADY_CLOSED(-1, 9),
|
||||
/**
|
||||
* <p>The stream status indicating credentials not valid</p>
|
||||
*/
|
||||
INVALID_CREDENTIALS(-1, 9),
|
||||
INVALID_CREDENTIALS(-1, 10),
|
||||
/**
|
||||
* <p>The stream status indicating that the implementation could not support a frame too large</p>
|
||||
*/
|
||||
FRAME_TOO_LARGE(-1, 10);
|
||||
FRAME_TOO_LARGE(-1, 11);
|
||||
|
||||
/**
|
||||
* @param version the SPDY protocol version
|
||||
|
|
|
@ -20,9 +20,6 @@ import java.nio.ByteBuffer;
|
|||
import java.util.EnumMap;
|
||||
|
||||
import org.eclipse.jetty.spdy.CompressionFactory;
|
||||
import org.eclipse.jetty.spdy.SessionException;
|
||||
import org.eclipse.jetty.spdy.api.SPDY;
|
||||
import org.eclipse.jetty.spdy.api.SessionStatus;
|
||||
import org.eclipse.jetty.spdy.frames.ControlFrame;
|
||||
import org.eclipse.jetty.spdy.frames.ControlFrameType;
|
||||
|
||||
|
@ -77,7 +74,6 @@ public abstract class ControlFrameParser
|
|||
if (buffer.remaining() >= 2)
|
||||
{
|
||||
version = (short)(buffer.getShort() & 0x7F_FF);
|
||||
checkVersion(version);
|
||||
state = State.TYPE;
|
||||
}
|
||||
else
|
||||
|
@ -95,7 +91,6 @@ public abstract class ControlFrameParser
|
|||
if (cursor == 0)
|
||||
{
|
||||
version &= 0x7F_FF;
|
||||
checkVersion(version);
|
||||
state = State.TYPE;
|
||||
}
|
||||
break;
|
||||
|
@ -171,12 +166,6 @@ public abstract class ControlFrameParser
|
|||
return false;
|
||||
}
|
||||
|
||||
private void checkVersion(short version)
|
||||
{
|
||||
if (version != SPDY.V2 && version != SPDY.V3)
|
||||
throw new SessionException(SessionStatus.PROTOCOL_ERROR, "Unrecognized version " + version);
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
state = State.VERSION;
|
||||
|
|
|
@ -19,8 +19,10 @@ package org.eclipse.jetty.spdy.parser;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.spdy.CompressionFactory;
|
||||
import org.eclipse.jetty.spdy.StreamException;
|
||||
import org.eclipse.jetty.spdy.api.Headers;
|
||||
import org.eclipse.jetty.spdy.api.SPDY;
|
||||
import org.eclipse.jetty.spdy.api.StreamStatus;
|
||||
import org.eclipse.jetty.spdy.api.SynInfo;
|
||||
import org.eclipse.jetty.spdy.frames.ControlFrameType;
|
||||
import org.eclipse.jetty.spdy.frames.SynStreamFrame;
|
||||
|
@ -77,6 +79,10 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
|
|||
}
|
||||
case ASSOCIATED_STREAM_ID:
|
||||
{
|
||||
// Now we know the streamId, we can do the version check
|
||||
// and if it is wrong, issue a RST_STREAM
|
||||
checkVersion(controlFrameParser.getVersion(), streamId);
|
||||
|
||||
if (buffer.remaining() >= 4)
|
||||
{
|
||||
associatedStreamId = buffer.getInt() & 0x7F_FF_FF_FF;
|
||||
|
@ -145,6 +151,12 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
|
|||
return false;
|
||||
}
|
||||
|
||||
private void checkVersion(short version, int streamId)
|
||||
{
|
||||
if (version != SPDY.V2 && version != SPDY.V3)
|
||||
throw new StreamException(streamId, StreamStatus.UNSUPPORTED_VERSION);
|
||||
}
|
||||
|
||||
private byte readPriority(short version, byte currByte)
|
||||
{
|
||||
// Right shift retains the sign bit when operated on a byte,
|
||||
|
|
|
@ -20,19 +20,51 @@ import java.nio.ByteBuffer;
|
|||
|
||||
public class UnknownControlFrameBodyParser extends ControlFrameBodyParser
|
||||
{
|
||||
private final ControlFrameParser controlFrameParser;
|
||||
private State state = State.BODY;
|
||||
private int remaining;
|
||||
|
||||
public UnknownControlFrameBodyParser(ControlFrameParser controlFrameParser)
|
||||
{
|
||||
this.remaining = controlFrameParser.getLength();
|
||||
this.controlFrameParser = controlFrameParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
int consumed = Math.min(remaining, buffer.remaining());
|
||||
buffer.position(buffer.position() + consumed);
|
||||
remaining -= consumed;
|
||||
return remaining == 0;
|
||||
switch (state)
|
||||
{
|
||||
case BODY:
|
||||
{
|
||||
remaining = controlFrameParser.getLength();
|
||||
state = State.CONSUME;
|
||||
// Fall down
|
||||
}
|
||||
case CONSUME:
|
||||
{
|
||||
int consume = Math.min(remaining, buffer.remaining());
|
||||
buffer.position(buffer.position() + consume);
|
||||
remaining -= consume;
|
||||
if (remaining > 0)
|
||||
return false;
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
state = State.BODY;
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
private enum State
|
||||
{
|
||||
BODY, CONSUME
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package org.eclipse.jetty.spdy.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.spdy.SessionException;
|
||||
import org.eclipse.jetty.spdy.StandardByteBufferPool;
|
||||
import org.eclipse.jetty.spdy.StandardCompressionFactory;
|
||||
import org.eclipse.jetty.spdy.StreamException;
|
||||
import org.eclipse.jetty.spdy.api.Headers;
|
||||
import org.eclipse.jetty.spdy.api.SPDY;
|
||||
import org.eclipse.jetty.spdy.api.SynInfo;
|
||||
import org.eclipse.jetty.spdy.frames.ControlFrame;
|
||||
import org.eclipse.jetty.spdy.frames.DataFrame;
|
||||
import org.eclipse.jetty.spdy.frames.SynStreamFrame;
|
||||
import org.eclipse.jetty.spdy.generator.Generator;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UnknownControlFrameTest
|
||||
{
|
||||
@Test
|
||||
public void testUnknownControlFrame() throws Exception
|
||||
{
|
||||
SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, new Headers());
|
||||
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
|
||||
ByteBuffer buffer = generator.control(frame);
|
||||
// Change the frame type to unknown
|
||||
buffer.putShort(2, (short)0);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(new StandardCompressionFactory.StandardDecompressor());
|
||||
parser.addListener(new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onControlFrame(ControlFrame frame)
|
||||
{
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataFrame(DataFrame frame, ByteBuffer data)
|
||||
{
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStreamException(StreamException x)
|
||||
{
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionException(SessionException x)
|
||||
{
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
parser.parse(buffer);
|
||||
|
||||
Assert.assertFalse(latch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
|
@ -1,48 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-parent</artifactId>
|
||||
<version>7.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-parent</artifactId>
|
||||
<version>7.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spdy-jetty-http-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Jetty :: SPDY :: Jetty HTTP Web Application</name>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spdy-jetty-http-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Jetty :: SPDY :: Jetty HTTP Web Application</name>
|
||||
|
||||
<build>
|
||||
<!--
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<configuration>
|
||||
<stopPort>8888</stopPort>
|
||||
<stopKey>quit</stopKey>
|
||||
<jvmArgs>
|
||||
-Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties
|
||||
-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar
|
||||
</jvmArgs>
|
||||
<jettyXml>${basedir}/src/main/config/jetty-spdy.xml</jettyXml>
|
||||
<contextPath>/</contextPath>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty-http</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<configuration>
|
||||
<stopPort>8888</stopPort>
|
||||
<stopKey>quit</stopKey>
|
||||
<jvmArgs>
|
||||
-Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties
|
||||
-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar
|
||||
</jvmArgs>
|
||||
<jettyXml>${basedir}/src/main/config/jetty-spdy.xml</jettyXml>
|
||||
<contextPath>/</contextPath>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty-http</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</build>
|
||||
-->
|
||||
</project>
|
|
@ -1,52 +1,60 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-parent</artifactId>
|
||||
<version>7.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spdy-jetty-http</artifactId>
|
||||
<name>Jetty :: SPDY :: Jetty HTTP Layer</name>
|
||||
|
||||
<build>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-parent</artifactId>
|
||||
<version>7.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spdy-jetty-http</artifactId>
|
||||
<name>Jetty :: SPDY :: Jetty HTTP Layer</name>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar </argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>eclipse-release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,57 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-parent</artifactId>
|
||||
<version>7.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spdy-jetty</artifactId>
|
||||
<name>Jetty :: SPDY :: Jetty Binding</name>
|
||||
|
||||
<build>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-parent</artifactId>
|
||||
<version>7.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spdy-jetty</artifactId>
|
||||
<name>Jetty :: SPDY :: Jetty Binding</name>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar </argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>eclipse-release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -53,9 +53,10 @@ public abstract class AbstractTest
|
|||
|
||||
protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
connector = newSPDYServerConnector(listener);
|
||||
if (connector == null)
|
||||
connector = newSPDYServerConnector(listener);
|
||||
connector.setPort(0);
|
||||
server = new Server();
|
||||
server.addConnector(connector);
|
||||
server.start();
|
||||
return new InetSocketAddress("localhost", connector.getLocalPort());
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
package org.eclipse.jetty.spdy;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.spdy.api.DataInfo;
|
||||
import org.eclipse.jetty.spdy.api.Handler;
|
||||
import org.eclipse.jetty.spdy.api.RstInfo;
|
||||
import org.eclipse.jetty.spdy.api.Session;
|
||||
import org.eclipse.jetty.spdy.api.SessionFrameListener;
|
||||
import org.eclipse.jetty.spdy.api.Stream;
|
||||
import org.eclipse.jetty.spdy.api.StreamFrameListener;
|
||||
import org.eclipse.jetty.spdy.api.StreamStatus;
|
||||
import org.eclipse.jetty.spdy.api.StringDataInfo;
|
||||
import org.eclipse.jetty.spdy.api.SynInfo;
|
||||
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ResetStreamTest extends AbstractTest
|
||||
{
|
||||
@Test
|
||||
public void testResetStreamIsRemoved() throws Exception
|
||||
{
|
||||
Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()), null);
|
||||
|
||||
Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
|
||||
session.rst(new RstInfo(stream.getId(), StreamStatus.CANCEL_STREAM)).get(5, TimeUnit.SECONDS);
|
||||
|
||||
Assert.assertEquals(0, session.getStreams().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefusedStreamIsRemoved() throws Exception
|
||||
{
|
||||
final AtomicReference<Session> serverSessionRef = new AtomicReference<>();
|
||||
final CountDownLatch synLatch = new CountDownLatch(1);
|
||||
final CountDownLatch rstLatch = new CountDownLatch(1);
|
||||
Session clientSession = startClient(startServer(new ServerSessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
Session serverSession = stream.getSession();
|
||||
serverSessionRef.set(serverSession);
|
||||
serverSession.rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
|
||||
synLatch.countDown();
|
||||
return null;
|
||||
}
|
||||
}), new SessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onRst(Session session, RstInfo rstInfo)
|
||||
{
|
||||
rstLatch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
clientSession.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
|
||||
|
||||
Assert.assertTrue(synLatch.await(5, TimeUnit.SECONDS));
|
||||
Session serverSession = serverSessionRef.get();
|
||||
Assert.assertEquals(0, serverSession.getStreams().size());
|
||||
|
||||
Assert.assertTrue(rstLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertEquals(0, clientSession.getStreams().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefusedStreamIgnoresData() throws Exception
|
||||
{
|
||||
final CountDownLatch synLatch = new CountDownLatch(1);
|
||||
final CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
final CountDownLatch rstLatch = new CountDownLatch(1);
|
||||
Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Refuse the stream, we must ignore data frames
|
||||
Assert.assertTrue(synLatch.await(5, TimeUnit.SECONDS));
|
||||
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
|
||||
return new StreamFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(Stream stream, DataInfo dataInfo)
|
||||
{
|
||||
dataLatch.countDown();
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
x.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}), new SessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onRst(Session session, RstInfo rstInfo)
|
||||
{
|
||||
rstLatch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
|
||||
stream.data(new StringDataInfo("data", true), 5, TimeUnit.SECONDS, new Handler.Adapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void completed(Void context)
|
||||
{
|
||||
synLatch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(rstLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package org.eclipse.jetty.spdy;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.spdy.api.Headers;
|
||||
import org.eclipse.jetty.spdy.api.SPDY;
|
||||
import org.eclipse.jetty.spdy.api.Stream;
|
||||
import org.eclipse.jetty.spdy.api.StreamFrameListener;
|
||||
import org.eclipse.jetty.spdy.api.StreamStatus;
|
||||
import org.eclipse.jetty.spdy.api.SynInfo;
|
||||
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
|
||||
import org.eclipse.jetty.spdy.frames.ControlFrame;
|
||||
import org.eclipse.jetty.spdy.frames.ControlFrameType;
|
||||
import org.eclipse.jetty.spdy.frames.RstStreamFrame;
|
||||
import org.eclipse.jetty.spdy.frames.SynStreamFrame;
|
||||
import org.eclipse.jetty.spdy.generator.Generator;
|
||||
import org.eclipse.jetty.spdy.parser.Parser;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UnsupportedVersionTest extends AbstractTest
|
||||
{
|
||||
@Test
|
||||
public void testSynWithUnsupportedVersion() throws Exception
|
||||
{
|
||||
final CountDownLatch synLatch = new CountDownLatch(1);
|
||||
InetSocketAddress address = startServer(new ServerSessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
synLatch.countDown();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Throwable x)
|
||||
{
|
||||
// Suppress exception logging for this test
|
||||
}
|
||||
});
|
||||
|
||||
SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, new Headers());
|
||||
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
|
||||
ByteBuffer buffer = generator.control(frame);
|
||||
// Replace the version byte with an unsupported version
|
||||
buffer.putShort(0, (short)0x8001);
|
||||
|
||||
SocketChannel channel = SocketChannel.open(address);
|
||||
channel.write(buffer);
|
||||
Assert.assertFalse(buffer.hasRemaining());
|
||||
|
||||
Assert.assertFalse(synLatch.await(1, TimeUnit.SECONDS));
|
||||
|
||||
buffer = ByteBuffer.allocate(1024);
|
||||
channel.read(buffer);
|
||||
buffer.flip();
|
||||
|
||||
final CountDownLatch rstLatch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(new StandardCompressionFactory.StandardDecompressor());
|
||||
parser.addListener(new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onControlFrame(ControlFrame frame)
|
||||
{
|
||||
Assert.assertSame(ControlFrameType.RST_STREAM, frame.getType());
|
||||
Assert.assertEquals(StreamStatus.UNSUPPORTED_VERSION.getCode(frame.getVersion()), ((RstStreamFrame)frame).getStatusCode());
|
||||
rstLatch.countDown();
|
||||
}
|
||||
});
|
||||
parser.parse(buffer);
|
||||
|
||||
Assert.assertTrue(rstLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
|
@ -232,10 +232,15 @@ public class CertificateValidator
|
|||
}
|
||||
|
||||
// Enable On-Line Certificate Status Protocol (OCSP) support
|
||||
Security.setProperty("ocsp.enable","true");
|
||||
|
||||
if (_enableOCSP)
|
||||
{
|
||||
Security.setProperty("ocsp.enable","true");
|
||||
}
|
||||
// Enable Certificate Revocation List Distribution Points (CRLDP) support
|
||||
System.setProperty("com.sun.security.enableCRLDP","true");
|
||||
if (_enableCRLDP)
|
||||
{
|
||||
System.setProperty("com.sun.security.enableCRLDP","true");
|
||||
}
|
||||
|
||||
// Build certification path
|
||||
CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams);
|
||||
|
|
Loading…
Reference in New Issue