Merge branch 'master' into release
This commit is contained in:
commit
cee44dcfbf
|
@ -1,4 +1,6 @@
|
|||
jetty-7.5.1-SNAPSHOT
|
||||
+ 356695 websocket packages should be provided
|
||||
+ 356749 WebSocket message length is computed wrongly when greater than 0xFFFF
|
||||
|
||||
jetty-7.5.0.v20110901 - 01 September 2011
|
||||
+ 356421 Upgraded websocket to draft 13 support
|
||||
|
@ -60,6 +62,12 @@ jetty-7.5.0.RC0 - 15 August 2011
|
|||
+ 354397 RewriteRegexRule handles special characters in regex group
|
||||
+ 354466 Typo in example config of jetty-plus.xml
|
||||
|
||||
jetty-7.4.5.v20110725 July 25th 2011
|
||||
+ 347484 / - > ${/} in some paths in grant codebases
|
||||
+ 352133 resolve some 1.5isms
|
||||
+ 352421 HttpURI paths beginning with '.'
|
||||
+ 352786 GzipFilter fails to pass parameters to GzipResponseWrapper
|
||||
|
||||
jetty-7.4.4.v20110707 - 07 July 2011
|
||||
+ 308851 Converted all jetty-client module tests to JUnit 4
|
||||
+ 345268 JDBCSessionManager does not work with maxInactiveInterval = -1
|
||||
|
|
|
@ -334,7 +334,9 @@ public class HttpFields
|
|||
{
|
||||
if (__cache.size()>__cacheSize)
|
||||
__cache.clear();
|
||||
__cache.putIfAbsent(value,buffer);
|
||||
Buffer b=__cache.putIfAbsent(value,buffer);
|
||||
if (b!=null)
|
||||
buffer=b;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
|
|
@ -35,8 +35,8 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
*/
|
||||
public class GzipResponseWrapper extends HttpServletResponseWrapper
|
||||
{
|
||||
public static int DEFAULT_BUFFER_SIZE = 8192;
|
||||
public static int DEFAULT_MIN_GZIP_SIZE = 256;
|
||||
public static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
public static final int DEFAULT_MIN_GZIP_SIZE = 256;
|
||||
|
||||
private HttpServletRequest _request;
|
||||
private Set<String> _mimeTypes;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
package org.eclipse.jetty.http.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -209,7 +210,7 @@ public class Constraint implements Cloneable, Serializable
|
|||
{
|
||||
return "SC{" + _name
|
||||
+ ","
|
||||
+ (_anyRole ? "*" : (_roles == null ? "-" : _roles.toString()))
|
||||
+ (_anyRole ? "*" : (_roles == null ? "-" : Arrays.asList(_roles).toString()))
|
||||
+ ","
|
||||
+ (_dataConstraint == DC_UNSET ? "DC_UNSET}" : (_dataConstraint == DC_NONE ? "NONE}" : (_dataConstraint == DC_INTEGRAL ? "INTEGRAL}" : "CONFIDENTIAL}")));
|
||||
}
|
||||
|
|
|
@ -152,12 +152,22 @@ public class Password extends Credential
|
|||
{
|
||||
case 1:
|
||||
buf.append('0');
|
||||
buf.append('0');
|
||||
buf.append('0');
|
||||
buf.append(x);
|
||||
break;
|
||||
case 2:
|
||||
buf.append('0');
|
||||
buf.append('0');
|
||||
buf.append(x);
|
||||
break;
|
||||
case 3:
|
||||
buf.append('0');
|
||||
buf.append(x);
|
||||
break;
|
||||
default:
|
||||
buf.append(x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
|
|
|
@ -387,7 +387,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
|
||||
private final ConcurrentLinkedQueue<Object> _changes = new ConcurrentLinkedQueue<Object>();
|
||||
|
||||
private Selector _selector;
|
||||
private volatile Selector _selector;
|
||||
|
||||
private volatile Thread _selecting;
|
||||
private int _jvmBug;
|
||||
|
@ -975,7 +975,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
// close endpoints and selector
|
||||
synchronized (this)
|
||||
{
|
||||
for (SelectionKey key:_selector.keys())
|
||||
Selector selector=_selector;
|
||||
for (SelectionKey key:selector.keys())
|
||||
{
|
||||
if (key==null)
|
||||
continue;
|
||||
|
@ -998,8 +999,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
_timeout.cancelAll();
|
||||
try
|
||||
{
|
||||
if (_selector != null)
|
||||
_selector.close();
|
||||
selector=_selector;
|
||||
if (selector != null)
|
||||
selector.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
|
@ -300,7 +300,12 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
catch (ThreadDeath x)
|
||||
{
|
||||
super.close();
|
||||
throw x;
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
LOG.debug(x);
|
||||
super.close();
|
||||
|
@ -444,8 +449,11 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
case BUFFER_OVERFLOW:
|
||||
case BUFFER_UNDERFLOW:
|
||||
LOG.warn("wrap {}",_result);
|
||||
_closing=true;
|
||||
break;
|
||||
case CLOSED:
|
||||
_closing=true;
|
||||
break;
|
||||
}
|
||||
|
||||
_outNIOBuffer.setPutIndex(put+_result.bytesProduced());
|
||||
|
@ -500,7 +508,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
|
||||
{
|
||||
int consumed=0;
|
||||
int available=header.length();
|
||||
int available=header==null?0:header.length();
|
||||
if (buffer!=null)
|
||||
available+=buffer.length();
|
||||
|
||||
|
@ -599,8 +607,11 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
case BUFFER_OVERFLOW:
|
||||
case BUFFER_UNDERFLOW:
|
||||
LOG.warn("unwrap {}",_result);
|
||||
_closing=true;
|
||||
break;
|
||||
case CLOSED:
|
||||
_closing=true;
|
||||
break;
|
||||
}
|
||||
_outNIOBuffer.setPutIndex(put+_result.bytesProduced());
|
||||
}
|
||||
|
@ -895,6 +906,8 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
case BUFFER_OVERFLOW:
|
||||
case BUFFER_UNDERFLOW:
|
||||
LOG.warn("unwrap {}",_result);
|
||||
_closing=true;
|
||||
return _result.bytesConsumed()>0?_result.bytesConsumed():-1;
|
||||
|
||||
case OK:
|
||||
return _result.bytesConsumed();
|
||||
|
@ -965,6 +978,8 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
case BUFFER_OVERFLOW:
|
||||
case BUFFER_UNDERFLOW:
|
||||
LOG.warn("unwrap {}",_result);
|
||||
_closing=true;
|
||||
return _result.bytesConsumed()>0?_result.bytesConsumed():-1;
|
||||
|
||||
case OK:
|
||||
return _result.bytesConsumed();
|
||||
|
|
|
@ -42,33 +42,4 @@ public class IOTest
|
|||
out.toString(),
|
||||
"The quick brown fox jumped over the lazy dog");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringSpeed()
|
||||
{
|
||||
String s="012345678901234567890000000000000000000000000";
|
||||
char[] ca = new char[s.length()];
|
||||
int loops=1000000;
|
||||
|
||||
long start=System.currentTimeMillis();
|
||||
long result=0;
|
||||
for (int loop=0;loop<loops;loop++)
|
||||
{
|
||||
for (int c=s.length();c-->0;)
|
||||
result+=s.charAt(c);
|
||||
}
|
||||
long end=System.currentTimeMillis();
|
||||
System.err.println("charAt "+(end-start)+" "+result);
|
||||
|
||||
start=System.currentTimeMillis();
|
||||
result=0;
|
||||
for (int loop=0;loop<loops;loop++)
|
||||
{
|
||||
s.getChars(0, s.length(), ca, 0);
|
||||
for (int c=s.length();c-->0;)
|
||||
result+=ca[c];
|
||||
}
|
||||
end=System.currentTimeMillis();
|
||||
System.err.println("getChars "+(end-start)+" "+result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class MongoTestServer extends AbstractTestServer
|
|||
_saveAllAttributes = saveAllAttributes;
|
||||
}
|
||||
|
||||
public SessionIdManager newSessionIdManager()
|
||||
public SessionIdManager newSessionIdManager(String config)
|
||||
{
|
||||
if ( _idManager != null )
|
||||
{
|
||||
|
|
|
@ -45,7 +45,7 @@ public class PolicyMonitorTest
|
|||
{
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
|
||||
Assert.assertEquals(1,count.get());
|
||||
monitor.stop();
|
||||
}
|
||||
|
@ -73,17 +73,14 @@ public class PolicyMonitorTest
|
|||
monitor.setScanInterval(1);
|
||||
|
||||
monitor.start();
|
||||
|
||||
while (! monitor.isInitialized() )
|
||||
{
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
monitor.waitForScan();
|
||||
monitor.waitForScan();
|
||||
|
||||
File permFile =new File(MavenTestingUtils.getTargetDir(),
|
||||
"test-classes/monitor-test-2/global-all-permission.policy");
|
||||
|
||||
// Wait so that time is definitely different
|
||||
Thread.sleep(10);
|
||||
// Wait so that time is definitely different
|
||||
monitor.waitForScan();
|
||||
permFile.setLastModified(System.currentTimeMillis());
|
||||
|
||||
monitor.waitForScan();
|
||||
|
|
|
@ -115,6 +115,7 @@ public class DigestAuthenticator extends LoginAuthenticator
|
|||
break;
|
||||
case ',':
|
||||
name = null;
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
|
|
|
@ -734,7 +734,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
{
|
||||
HttpSessionEvent event=new HttpSessionEvent(session);
|
||||
for (HttpSessionListener listener : _sessionListeners)
|
||||
listener.sessionCreated(event);
|
||||
listener.sessionDestroyed(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ public class HttpConnectionTest
|
|||
response=connector.getResponses("GET /foo/bar%c0%00 HTTP/1.1\n"+
|
||||
"Host: localhost\n"+
|
||||
"\015\012");
|
||||
checkContains(response,0,"pathInfo=/foo/bar?");
|
||||
checkContains(response,0,"HTTP/1.1 400");
|
||||
|
||||
response=connector.getResponses("GET /bad/utf8%c1 HTTP/1.1\n"+
|
||||
"Host: localhost\n"+
|
||||
|
|
|
@ -142,8 +142,10 @@ public class ServletContextHandler extends ContextHandler
|
|||
protected void doStop() throws Exception
|
||||
{
|
||||
super.doStop();
|
||||
_decorators.clear();
|
||||
_wrapper.setHandler(null);
|
||||
if (_decorators != null)
|
||||
_decorators.clear();
|
||||
if (_wrapper != null)
|
||||
_wrapper.setHandler(null);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.IllegalFormatCodePointException;
|
||||
|
||||
public abstract class Utf8Appendable
|
||||
{
|
||||
|
@ -69,6 +70,7 @@ public abstract class Utf8Appendable
|
|||
_appendable.append('?');
|
||||
_more=0;
|
||||
_bits=0;
|
||||
throw new NotUtf8Exception();
|
||||
}
|
||||
else
|
||||
_appendable.append((char)(0x7f&b));
|
||||
|
@ -81,6 +83,7 @@ public abstract class Utf8Appendable
|
|||
_appendable.append('?');
|
||||
_more=0;
|
||||
_bits=0;
|
||||
throw new NotUtf8Exception();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -116,7 +119,7 @@ public abstract class Utf8Appendable
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("!utf8");
|
||||
throw new NotUtf8Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +130,7 @@ public abstract class Utf8Appendable
|
|||
_appendable.append('?');
|
||||
_more=0;
|
||||
_bits=0;
|
||||
throw new IllegalArgumentException("!utf8");
|
||||
throw new NotUtf8Exception();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -139,4 +142,12 @@ public abstract class Utf8Appendable
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class NotUtf8Exception extends IllegalStateException
|
||||
{
|
||||
public NotUtf8Exception()
|
||||
{
|
||||
super("!UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,7 +60,7 @@ public class Utf8StringBuffer extends Utf8Appendable
|
|||
public StringBuffer getStringBuffer()
|
||||
{
|
||||
if (_more!=0)
|
||||
throw new IllegalStateException("!utf8");
|
||||
throw new NotUtf8Exception();
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class Utf8StringBuffer extends Utf8Appendable
|
|||
public String toString()
|
||||
{
|
||||
if (_more!=0)
|
||||
throw new IllegalStateException("!utf8");
|
||||
throw new NotUtf8Exception();
|
||||
return _buffer.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public class Utf8StringBuilder extends Utf8Appendable
|
|||
public StringBuilder getStringBuilder()
|
||||
{
|
||||
if (_more!=0)
|
||||
throw new IllegalStateException("!utf8");
|
||||
throw new NotUtf8Exception();
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ public class Utf8StringBuilder extends Utf8Appendable
|
|||
public String toString()
|
||||
{
|
||||
if (_more!=0)
|
||||
throw new IllegalStateException("!utf8");
|
||||
throw new NotUtf8Exception();
|
||||
return _buffer.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,9 +114,9 @@ public class FileResource extends URLResource
|
|||
if (_urlString.endsWith("/"))
|
||||
_urlString=_urlString.substring(0,_urlString.length()-1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
FileResource(URL url, URLConnection connection, File file)
|
||||
{
|
||||
|
|
|
@ -166,8 +166,7 @@ public abstract class Resource implements ResourceFactory
|
|||
|
||||
URLConnection connection=url.openConnection();
|
||||
connection.setUseCaches(useCaches);
|
||||
FileResource fileResource= new FileResource(url,connection,file);
|
||||
return fileResource;
|
||||
return new FileResource(url,connection,file);
|
||||
}
|
||||
catch(Exception e2)
|
||||
{
|
||||
|
@ -199,6 +198,18 @@ public abstract class Resource implements ResourceFactory
|
|||
return newResource(url);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static Resource newResource (File file)
|
||||
throws MalformedURLException, IOException
|
||||
{
|
||||
file = file.getCanonicalFile();
|
||||
URL url = Resource.toURL(file);
|
||||
|
||||
URLConnection connection = url.openConnection();
|
||||
FileResource fileResource = new FileResource(url, connection, file);
|
||||
return fileResource;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Construct a system resource from a string.
|
||||
* The resource is tried as classloader resource before being
|
||||
|
|
|
@ -50,7 +50,7 @@ public class Utf8StringBufferTest
|
|||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertTrue(e.toString().indexOf("!utf8")>=0);
|
||||
assertTrue(e.toString().indexOf("!UTF-8")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,16 @@ public class Utf8StringBufferTest
|
|||
bytes[4]=(byte)0x00;
|
||||
|
||||
Utf8StringBuffer buffer = new Utf8StringBuffer();
|
||||
for (int i=0;i<bytes.length;i++)
|
||||
buffer.append(bytes[i]);
|
||||
try
|
||||
{
|
||||
for (int i=0;i<bytes.length;i++)
|
||||
buffer.append(bytes[i]);
|
||||
assertTrue(false);
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertTrue(e.toString().indexOf("!UTF-8")>=0);
|
||||
}
|
||||
assertEquals("abc?",buffer.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class Utf8StringBuilderTest
|
|||
assertEquals(source, buffer.toString());
|
||||
assertTrue(buffer.toString().endsWith("jetty"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testShort()
|
||||
throws Exception
|
||||
|
@ -50,7 +50,7 @@ public class Utf8StringBuilderTest
|
|||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertTrue(e.toString().indexOf("!utf8")>=0);
|
||||
assertTrue(e.toString().indexOf("!UTF-8")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,9 +64,17 @@ public class Utf8StringBuilderTest
|
|||
bytes[4]=(byte)0x00;
|
||||
|
||||
Utf8StringBuilder buffer = new Utf8StringBuilder();
|
||||
for (int i=0;i<bytes.length;i++)
|
||||
buffer.append(bytes[i]);
|
||||
assertEquals("abc?",buffer.toString());
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < bytes.length; i++)
|
||||
buffer.append(bytes[i]);
|
||||
assertTrue(false);
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertTrue(e.toString().indexOf("!UTF-8")>=0);
|
||||
}
|
||||
assertEquals("abc?", buffer.toString());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.util.EventListener;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpSessionActivationListener;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
|
@ -60,9 +59,9 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
|
|||
* The handlers are configured by pluggable configuration classes, with
|
||||
* the default being {@link org.eclipse.jetty.webapp.WebXmlConfiguration} and
|
||||
* {@link org.eclipse.jetty.webapp.JettyWebXmlConfiguration}.
|
||||
*
|
||||
*
|
||||
* @org.apache.xbean.XBean description="Creates a servlet web application at a given context from a resource base"
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class WebAppContext extends ServletContextHandler implements WebAppClassLoader.Context
|
||||
{
|
||||
|
@ -75,7 +74,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
public final static String SERVER_CONFIG = "org.eclipse.jetty.webapp.configuration";
|
||||
public final static String SERVER_SYS_CLASSES = "org.eclipse.jetty.webapp.systemClasses";
|
||||
public final static String SERVER_SRV_CLASSES = "org.eclipse.jetty.webapp.serverClasses";
|
||||
|
||||
|
||||
private static String[] __dftConfigurationClasses =
|
||||
{
|
||||
"org.eclipse.jetty.webapp.WebInfConfiguration",
|
||||
|
@ -85,38 +84,40 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
|
||||
"org.eclipse.jetty.webapp.TagLibConfiguration"
|
||||
} ;
|
||||
|
||||
// System classes are classes that cannot be replaced by
|
||||
// the web application, and they are *always* loaded via
|
||||
|
||||
// System classes are classes that cannot be replaced by
|
||||
// the web application, and they are *always* loaded via
|
||||
// system classloader.
|
||||
public final static String[] __dftSystemClasses =
|
||||
public final static String[] __dftSystemClasses =
|
||||
{
|
||||
"java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)
|
||||
"java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)
|
||||
"javax.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)
|
||||
"org.xml.", // needed by javax.xml
|
||||
"org.w3c.", // needed by javax.xml
|
||||
"org.apache.commons.logging.", // TODO: review if special case still needed
|
||||
"org.apache.commons.logging.", // TODO: review if special case still needed
|
||||
"org.eclipse.jetty.continuation.", // webapp cannot change continuation classes
|
||||
"org.eclipse.jetty.jndi.", // webapp cannot change naming classes
|
||||
"org.eclipse.jetty.plus.jaas.", // webapp cannot change jaas classes
|
||||
"org.eclipse.jetty.websocket.", // WebSocket is a jetty extension
|
||||
"org.eclipse.jetty.servlet.DefaultServlet" // webapp cannot change default servlets
|
||||
"org.eclipse.jetty.websocket.WebSocket", // WebSocket is a jetty extension
|
||||
"org.eclipse.jetty.websocket.WebSocketFactory", // WebSocket is a jetty extension
|
||||
"org.eclipse.jetty.servlet.DefaultServlet" // webapp cannot change default servlets
|
||||
} ;
|
||||
|
||||
|
||||
// Server classes are classes that are hidden from being
|
||||
// loaded by the web application using system classloader,
|
||||
// so if web application needs to load any of such classes,
|
||||
// it has to include them in its distribution.
|
||||
public final static String[] __dftServerClasses =
|
||||
public final static String[] __dftServerClasses =
|
||||
{
|
||||
"-org.eclipse.jetty.continuation.", // don't hide continuation classes
|
||||
"-org.eclipse.jetty.jndi.", // don't hide naming classes
|
||||
"-org.eclipse.jetty.plus.jaas.", // don't hide jaas classes
|
||||
"-org.eclipse.jetty.websocket.", // don't hide websocket extension
|
||||
"-org.eclipse.jetty.websocket.WebSocket", // WebSocket is a jetty extension
|
||||
"-org.eclipse.jetty.websocket.WebSocketFactory", // WebSocket is a jetty extension
|
||||
"-org.eclipse.jetty.servlet.DefaultServlet", // don't hide default servlet
|
||||
"-org.eclipse.jetty.servlet.listener.", //don't hide useful listeners
|
||||
"-org.eclipse.jetty.servlet.listener.", // don't hide useful listeners
|
||||
"org.eclipse.jetty." // hide other jetty classes
|
||||
} ;
|
||||
} ;
|
||||
|
||||
private String[] _configurationClasses = __dftConfigurationClasses;
|
||||
private ClasspathPattern _systemClasses = null;
|
||||
|
@ -135,12 +136,12 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
private PermissionCollection _permissions;
|
||||
|
||||
private String[] _contextWhiteList = null;
|
||||
|
||||
|
||||
private File _tmpDir;
|
||||
private String _war;
|
||||
private String _extraClasspath;
|
||||
private Throwable _unavailableException;
|
||||
|
||||
|
||||
private Map<String, String> _resourceAliases;
|
||||
private boolean _ownClassLoader=false;
|
||||
private boolean _configurationDiscovered=true;
|
||||
|
@ -148,8 +149,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
private boolean _configurationsSet=false;
|
||||
private boolean _allowDuplicateFragmentNames = false;
|
||||
private boolean _throwUnavailableOnStartupException = false;
|
||||
|
||||
|
||||
|
||||
|
||||
private MetaData _metadata=new MetaData();
|
||||
|
||||
public static WebAppContext getCurrentWebAppContext()
|
||||
|
@ -163,15 +164,15 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebAppContext()
|
||||
{
|
||||
super(SESSIONS|SECURITY);
|
||||
super(SESSIONS|SECURITY);
|
||||
_scontext=new Context();
|
||||
setErrorHandler(new ErrorPageErrorHandler());
|
||||
setErrorHandler(new ErrorPageErrorHandler());
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param contextPath The context path
|
||||
|
@ -183,9 +184,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_scontext=new Context();
|
||||
setContextPath(contextPath);
|
||||
setWar(webApp);
|
||||
setErrorHandler(new ErrorPageErrorHandler());
|
||||
setErrorHandler(new ErrorPageErrorHandler());
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param parent The parent HandlerContainer.
|
||||
|
@ -197,7 +198,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
super(parent,contextPath,SESSIONS|SECURITY);
|
||||
_scontext=new Context();
|
||||
setWar(webApp);
|
||||
setErrorHandler(new ErrorPageErrorHandler());
|
||||
setErrorHandler(new ErrorPageErrorHandler());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -215,7 +216,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_scontext = new Context();
|
||||
setErrorHandler(errorHandler != null ? errorHandler : new ErrorPageErrorHandler());
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param servletContextName The servletContextName to set.
|
||||
|
@ -228,7 +229,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
if (cl!=null && cl instanceof WebAppClassLoader && servletContextName!=null)
|
||||
((WebAppClassLoader)cl).setName(servletContextName);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get an exception that caused the webapp to be unavailable
|
||||
* @return A throwable if the webapp is unavailable or null
|
||||
|
@ -238,7 +239,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return _unavailableException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set Resource Alias.
|
||||
* Resource aliases map resource uri's within a context.
|
||||
|
@ -261,13 +262,13 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return null;
|
||||
return _resourceAliases;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setResourceAliases(Map<String, String> map)
|
||||
{
|
||||
_resourceAliases = map;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getResourceAlias(String alias)
|
||||
{
|
||||
|
@ -292,16 +293,16 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
public void setClassLoader(ClassLoader classLoader)
|
||||
{
|
||||
super.setClassLoader(classLoader);
|
||||
|
||||
|
||||
// if ( !(classLoader instanceof WebAppClassLoader) )
|
||||
// {
|
||||
// LOG.info("NOTE: detected a classloader which is not an instance of WebAppClassLoader being set on WebAppContext, some typical class and resource locations may be missing on: " + toString() );
|
||||
// }
|
||||
|
||||
|
||||
if (classLoader!=null && classLoader instanceof WebAppClassLoader && getDisplayName()!=null)
|
||||
((WebAppClassLoader)classLoader).setName(getDisplayName());
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public Resource getResource(String uriInContext) throws MalformedURLException
|
||||
|
@ -319,7 +320,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
resource= super.getResource(uriInContext);
|
||||
if (resource != null && resource.exists())
|
||||
return resource;
|
||||
|
||||
|
||||
uriInContext = getResourceAlias(uriInContext);
|
||||
}
|
||||
catch (IOException e)
|
||||
|
@ -335,11 +336,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Is the context Automatically configured.
|
||||
*
|
||||
*
|
||||
* @return true if configuration discovery.
|
||||
*/
|
||||
public boolean isConfigurationDiscovered()
|
||||
|
@ -361,7 +362,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
_configurationDiscovered = discovered;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Pre configure the web application.
|
||||
* <p>
|
||||
|
@ -372,7 +373,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
* <li>Setup the default System classes by calling {@link #loadSystemClasses()}
|
||||
* <li>Setup the default Server classes by calling <code>loadServerClasses()</code>
|
||||
* <li>Instantiates a classload (if one is not already set)
|
||||
* <li>Calls the {@link Configuration#preConfigure(WebAppContext)} method of all
|
||||
* <li>Calls the {@link Configuration#preConfigure(WebAppContext)} method of all
|
||||
* Configuration instances.
|
||||
* </ul>
|
||||
* @throws Exception
|
||||
|
@ -384,7 +385,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
// Setup system classes
|
||||
loadSystemClasses();
|
||||
|
||||
|
||||
// Setup server classes
|
||||
loadServerClasses();
|
||||
|
||||
|
@ -408,8 +409,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
loader=loader.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for configuration
|
||||
|
||||
// Prepare for configuration
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
{
|
||||
LOG.debug("preConfigure {} with {}",this,_configurations[i]);
|
||||
|
@ -427,10 +428,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_configurations[i].configure(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void postConfigure() throws Exception
|
||||
{
|
||||
{
|
||||
// Clean up after configuration
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
{
|
||||
|
@ -438,7 +439,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_configurations[i].postConfigure(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see org.eclipse.thread.AbstractLifeCycle#doStart()
|
||||
|
@ -466,7 +467,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see org.eclipse.thread.AbstractLifeCycle#doStop()
|
||||
|
@ -480,11 +481,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
for (int i=_configurations.length;i-->0;)
|
||||
_configurations[i].deconfigure(this);
|
||||
|
||||
|
||||
if (_metadata != null)
|
||||
_metadata.clear();
|
||||
_metadata=new MetaData();
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -495,19 +496,19 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_unavailableException=null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
// Prepare for configuration
|
||||
// Prepare for configuration
|
||||
MultiException mx=new MultiException();
|
||||
if (_configurations!=null)
|
||||
{
|
||||
for (int i=_configurations.length;i-->0;)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
_configurations[i].destroy(this);
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -535,7 +536,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
String displayName = getDisplayName();
|
||||
if (displayName == null)
|
||||
displayName = "WebApp@"+connectors.hashCode();
|
||||
|
||||
|
||||
LOG.info(displayName + " at http://" + connectorName + getContextPath());
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +549,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
return _configurationClasses;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the configurations.
|
||||
|
@ -557,7 +558,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
return _configurations;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* The default descriptor is a web.xml format file that is applied to the context before the standard WEB-INF/web.xml
|
||||
|
@ -567,7 +568,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
return _defaultsDescriptor;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* The override descriptor is a web.xml format file that is applied to the context after the standard WEB-INF/web.xml
|
||||
|
@ -580,7 +581,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return null;
|
||||
return _overrideDescriptors.get(0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* An override descriptor is a web.xml format file that is applied to the context after the standard WEB-INF/web.xml
|
||||
|
@ -590,7 +591,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
return Collections.unmodifiableList(_overrideDescriptors);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the permissions.
|
||||
|
@ -609,7 +610,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
if (_serverClasses == null)
|
||||
loadServerClasses();
|
||||
|
||||
|
||||
return _serverClasses.getPatterns();
|
||||
}
|
||||
|
||||
|
@ -617,10 +618,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
if (_serverClasses == null)
|
||||
loadServerClasses();
|
||||
|
||||
|
||||
_serverClasses.addPattern(classname);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see #setSystemClasses(String[])
|
||||
|
@ -630,25 +631,25 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
if (_systemClasses == null)
|
||||
loadSystemClasses();
|
||||
|
||||
|
||||
return _systemClasses.getPatterns();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addSystemClass(String classname)
|
||||
{
|
||||
if (_systemClasses == null)
|
||||
loadSystemClasses();
|
||||
|
||||
|
||||
_systemClasses.addPattern(classname);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isServerClass(String name)
|
||||
{
|
||||
if (_serverClasses == null)
|
||||
loadServerClasses();
|
||||
|
||||
|
||||
return _serverClasses.match(name);
|
||||
}
|
||||
|
||||
|
@ -657,16 +658,16 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
if (_systemClasses == null)
|
||||
loadSystemClasses();
|
||||
|
||||
|
||||
return _systemClasses.match(name);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void loadSystemClasses()
|
||||
{
|
||||
if (_systemClasses != null)
|
||||
return;
|
||||
|
||||
|
||||
//look for a Server attribute with the list of System classes
|
||||
//to apply to every web application. If not present, use our defaults.
|
||||
Server server = getServer();
|
||||
|
@ -676,17 +677,17 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
if (systemClasses != null && systemClasses instanceof String[])
|
||||
_systemClasses = new ClasspathPattern((String[])systemClasses);
|
||||
}
|
||||
|
||||
|
||||
if (_systemClasses == null)
|
||||
_systemClasses = new ClasspathPattern(__dftSystemClasses);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void loadServerClasses()
|
||||
{
|
||||
if (_serverClasses != null)
|
||||
return;
|
||||
|
||||
|
||||
//look for a Server attribute with the list of Server classes
|
||||
//to apply to every web application. If not present, use our defaults.
|
||||
Server server = getServer();
|
||||
|
@ -696,11 +697,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
if (serverClasses != null || serverClasses instanceof String[])
|
||||
_serverClasses = new ClasspathPattern((String[])serverClasses);
|
||||
}
|
||||
|
||||
|
||||
if (_serverClasses == null)
|
||||
_serverClasses = new ClasspathPattern(__dftServerClasses);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the war as a file or URL string (Resource)
|
||||
|
@ -722,10 +723,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
Resource web_inf= super.getBaseResource().addPath("WEB-INF/");
|
||||
if (!web_inf.exists() || !web_inf.isDirectory())
|
||||
return null;
|
||||
|
||||
|
||||
return web_inf;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the distributable.
|
||||
|
@ -764,35 +765,35 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return True if the classloader should delegate first to the parent
|
||||
* classloader (standard java behaviour) or false if the classloader
|
||||
* should first try to load from WEB-INF/lib or WEB-INF/classes (servlet
|
||||
* @return True if the classloader should delegate first to the parent
|
||||
* classloader (standard java behaviour) or false if the classloader
|
||||
* should first try to load from WEB-INF/lib or WEB-INF/classes (servlet
|
||||
* spec recommendation).
|
||||
*/
|
||||
public boolean isParentLoaderPriority()
|
||||
{
|
||||
return _parentLoaderPriority;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String[] getDefaultConfigurationClasses ()
|
||||
{
|
||||
return __dftConfigurationClasses;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String[] getDefaultServerClasses ()
|
||||
{
|
||||
return __dftServerClasses;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String[] getDefaultSystemClasses ()
|
||||
{
|
||||
return __dftSystemClasses;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void loadConfigurations()
|
||||
throws Exception
|
||||
|
@ -811,17 +812,17 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_configurations[i]=(Configuration)Loader.loadClass(this.getClass(), _configurationClasses[i]).newInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected boolean isProtectedTarget(String target)
|
||||
{
|
||||
while (target.startsWith("//"))
|
||||
target=URIUtil.compactPath(target);
|
||||
|
||||
|
||||
return StringUtil.startsWithIgnoreCase(target, "/web-inf") || StringUtil.startsWithIgnoreCase(target, "/meta-inf");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
|
@ -843,7 +844,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_configurationClassesSet = true;
|
||||
_configurations=null;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param configurations The configurations to set.
|
||||
|
@ -877,7 +878,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_overrideDescriptors.clear();
|
||||
_overrideDescriptors.add(overrideDescriptor);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* The override descriptor is a web.xml format file that is applied to the context after the standard WEB-INF/web.xml
|
||||
|
@ -888,7 +889,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_overrideDescriptors.clear();
|
||||
_overrideDescriptors.addAll(overrideDescriptors);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* The override descriptor is a web.xml format file that is applied to the context after the standard WEB-INF/web.xml
|
||||
|
@ -916,7 +917,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
_descriptor=descriptor;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param distributable The distributable to set.
|
||||
|
@ -932,13 +933,13 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
if (_sessionHandler!=null)
|
||||
_sessionHandler.clearEventListeners();
|
||||
|
||||
|
||||
super.setEventListeners(eventListeners);
|
||||
|
||||
|
||||
for (int i=0; eventListeners!=null && i<eventListeners.length;i ++)
|
||||
{
|
||||
EventListener listener = eventListeners[i];
|
||||
|
||||
|
||||
if ((listener instanceof HttpSessionActivationListener)
|
||||
|| (listener instanceof HttpSessionAttributeListener)
|
||||
|| (listener instanceof HttpSessionBindingListener)
|
||||
|
@ -947,7 +948,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
if (_sessionHandler!=null)
|
||||
_sessionHandler.addEventListener(listener);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,11 +959,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
*/
|
||||
@Override
|
||||
public void addEventListener(EventListener listener)
|
||||
{
|
||||
{
|
||||
setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(), listener, EventListener.class));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param extractWAR True if war files are extracted
|
||||
|
@ -971,7 +972,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
_extractWAR = extractWAR;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param copy True if the webdir is copied (to allow hot replacement of jars)
|
||||
|
@ -1007,10 +1008,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
_permissions = permissions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the context white list
|
||||
*
|
||||
*
|
||||
* In certain circumstances you want may want to deny access of one webapp from another
|
||||
* when you may not fully trust the webapp. Setting this white list will enable a
|
||||
* check when a servlet called getContext(String), validating that the uriInPath
|
||||
|
@ -1041,7 +1042,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
_serverClasses = new ClasspathPattern(serverClasses);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the system classes patterns.
|
||||
|
@ -1061,7 +1062,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
_systemClasses = new ClasspathPattern(systemClasses);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set temporary directory for context.
|
||||
|
@ -1087,7 +1088,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite()))
|
||||
throw new IllegalArgumentException("Bad temp directory: "+dir);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (dir!=null)
|
||||
|
@ -1100,13 +1101,13 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_tmpDir=dir;
|
||||
setAttribute(TEMPDIR,_tmpDir);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public File getTempDirectory ()
|
||||
{
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param war The war to set as a file name or URL
|
||||
|
@ -1154,14 +1155,14 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
this._logUrlOnStart = logOnStart;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void setServer(Server server)
|
||||
{
|
||||
super.setServer(server);
|
||||
//if we haven't been given a set of configuration instances to
|
||||
//if we haven't been given a set of configuration instances to
|
||||
//use, and we haven't been given a set of configuration classes
|
||||
//to use, use the configuration classes that came from the
|
||||
//Server (if there are any)
|
||||
|
@ -1172,46 +1173,46 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
setConfigurationClasses(serverConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isAllowDuplicateFragmentNames()
|
||||
{
|
||||
return _allowDuplicateFragmentNames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setAllowDuplicateFragmentNames(boolean allowDuplicateFragmentNames)
|
||||
{
|
||||
_allowDuplicateFragmentNames = allowDuplicateFragmentNames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setThrowUnavailableOnStartupException (boolean throwIfStartupException) {
|
||||
_throwUnavailableOnStartupException = throwIfStartupException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isThrowUnavailableOnStartupException () {
|
||||
return _throwUnavailableOnStartupException;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void startContext()
|
||||
throws Exception
|
||||
{
|
||||
configure();
|
||||
|
||||
|
||||
//resolve the metadata
|
||||
_metadata.resolve(this);
|
||||
|
||||
|
||||
super.startContext();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public class Context extends ServletContextHandler.Context
|
||||
{
|
||||
|
@ -1221,7 +1222,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
Resource resource=WebAppContext.this.getResource(path);
|
||||
if (resource==null || !resource.exists())
|
||||
return null;
|
||||
|
||||
|
||||
// Should we go to the original war?
|
||||
if (resource.isDirectory() && resource instanceof ResourceCollection && !WebAppContext.this.isExtractWAR())
|
||||
{
|
||||
|
@ -1232,7 +1233,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return resources[i].getURL();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return resource.getURL();
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1242,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
public ServletContext getContext(String uripath)
|
||||
{
|
||||
ServletContext servletContext = super.getContext(uripath);
|
||||
|
||||
|
||||
if ( servletContext != null && _contextWhiteList != null )
|
||||
{
|
||||
for ( String context : _contextWhiteList )
|
||||
|
@ -1251,7 +1252,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return servletContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,77 +1,100 @@
|
|||
<?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/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>7.5.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-websocket</artifactId>
|
||||
<name>Jetty :: Websocket</name>
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.websocket</bundle-symbolic-name>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>artifact-jar</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-jar</id>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<onlyAnalyze>org.eclipse.jetty.websocket.*</onlyAnalyze>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>7.5.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-websocket</artifactId>
|
||||
<name>Jetty :: Websocket</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.websocket</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>artifact-jar</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-jar</id>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<onlyAnalyze>org.eclipse.jetty.websocket.*</onlyAnalyze>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -11,6 +11,9 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* @TODO Implement proposed deflate frame draft
|
||||
*/
|
||||
public class DeflateFrameExtension extends AbstractExtension
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DeflateFrameExtension.class);
|
||||
|
@ -18,7 +21,7 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
private int _minLength=8;
|
||||
private Deflater _deflater;
|
||||
private Inflater _inflater;
|
||||
|
||||
|
||||
public DeflateFrameExtension()
|
||||
{
|
||||
super("x-deflate-frame");
|
||||
|
@ -32,10 +35,10 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
if(super.init(parameters))
|
||||
{
|
||||
_minLength=getInitParameter("minLength",_minLength);
|
||||
|
||||
|
||||
_deflater=new Deflater();
|
||||
_inflater=new Inflater();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -46,7 +49,7 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
*/
|
||||
@Override
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
{
|
||||
{
|
||||
if (getConnection().isControl(opcode) || !isFlag(flags,1))
|
||||
{
|
||||
super.onFrame(flags,opcode,buffer);
|
||||
|
@ -55,7 +58,7 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
|
||||
if (buffer.array()==null)
|
||||
buffer=buffer.asMutableBuffer();
|
||||
|
||||
|
||||
int length=0xff&buffer.get();
|
||||
if (length>=0x7e)
|
||||
{
|
||||
|
@ -63,10 +66,10 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
length=0;
|
||||
while(b-->0)
|
||||
length=0x100*length+(0xff&buffer.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO check a max framesize
|
||||
|
||||
|
||||
_inflater.setInput(buffer.array(),buffer.getIndex(),buffer.length());
|
||||
ByteArrayBuffer buf = new ByteArrayBuffer(length);
|
||||
try
|
||||
|
@ -99,12 +102,12 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
super.addFrame(clearFlag(flags,1),opcode,content,offset,length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// prepare the uncompressed input
|
||||
_deflater.reset();
|
||||
_deflater.setInput(content,offset,length);
|
||||
_deflater.finish();
|
||||
|
||||
|
||||
// prepare the output buffer
|
||||
byte[] out= new byte[length];
|
||||
int out_offset=0;
|
||||
|
@ -113,10 +116,10 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
if (length>0xffff)
|
||||
{
|
||||
out[out_offset++]=0x7f;
|
||||
out[out_offset++]=(byte)((length>>56)&0x7f);
|
||||
out[out_offset++]=(byte)((length>>48)&0xff);
|
||||
out[out_offset++]=(byte)((length>>40)&0xff);
|
||||
out[out_offset++]=(byte)((length>>32)&0xff);
|
||||
out[out_offset++]=(byte)0;
|
||||
out[out_offset++]=(byte)0;
|
||||
out[out_offset++]=(byte)0;
|
||||
out[out_offset++]=(byte)0;
|
||||
out[out_offset++]=(byte)((length>>24)&0xff);
|
||||
out[out_offset++]=(byte)((length>>16)&0xff);
|
||||
out[out_offset++]=(byte)((length>>8)&0xff);
|
||||
|
@ -125,7 +128,7 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
else if (length >=0x7e)
|
||||
{
|
||||
out[out_offset++]=0x7e;
|
||||
out[out_offset++]=(byte)(byte)(length>>8);
|
||||
out[out_offset++]=(byte)(length>>8);
|
||||
out[out_offset++]=(byte)(length&0xff);
|
||||
}
|
||||
else
|
||||
|
@ -134,7 +137,7 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
}
|
||||
|
||||
int l = _deflater.deflate(out,out_offset,length-out_offset);
|
||||
|
||||
|
||||
if (_deflater.finished())
|
||||
super.addFrame(setFlag(flags,1),opcode,out,0,l+out_offset);
|
||||
else
|
||||
|
|
|
@ -3,22 +3,23 @@ package org.eclipse.jetty.websocket;
|
|||
|
||||
public class FixedMaskGen implements MaskGen
|
||||
{
|
||||
final byte[] _mask;
|
||||
private final byte[] _mask;
|
||||
|
||||
public FixedMaskGen()
|
||||
{
|
||||
_mask=new byte[]{(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff};
|
||||
this(new byte[]{(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff});
|
||||
}
|
||||
|
||||
|
||||
public FixedMaskGen(byte[] mask)
|
||||
{
|
||||
_mask=mask;
|
||||
_mask=new byte[4];
|
||||
// Copy to avoid that external code keeps a reference
|
||||
// to the array parameter to modify masking on-the-fly
|
||||
System.arraycopy(mask, 0, _mask, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
public void genMask(byte[] mask)
|
||||
{
|
||||
mask[0]=_mask[0];
|
||||
mask[1]=_mask[1];
|
||||
mask[2]=_mask[2];
|
||||
mask[3]=_mask[3];
|
||||
System.arraycopy(_mask, 0, mask, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,23 @@ import java.util.Random;
|
|||
|
||||
public class RandomMaskGen implements MaskGen
|
||||
{
|
||||
final Random _random;
|
||||
private final Random _random;
|
||||
|
||||
public RandomMaskGen()
|
||||
{
|
||||
_random=new Random();
|
||||
this(new Random());
|
||||
}
|
||||
|
||||
|
||||
public RandomMaskGen(Random random)
|
||||
{
|
||||
_random=random;
|
||||
}
|
||||
|
||||
|
||||
public void genMask(byte[] mask)
|
||||
{
|
||||
// The assumption is that this code is always called
|
||||
// with an external lock held to prevent concurrent access
|
||||
// Otherwise we need to synchronize on the _random.
|
||||
_random.nextBytes(mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -21,7 +21,7 @@ import org.eclipse.jetty.io.BuffersFactory;
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** The WebSocket Buffer Pool.
|
||||
*
|
||||
*
|
||||
* The normal buffers are byte array buffers so that user processes
|
||||
* can access directly. However the generator uses direct buffers
|
||||
* for the final output stage as they are filled in bulk and are more
|
||||
|
@ -31,24 +31,23 @@ public class WebSocketBuffers
|
|||
{
|
||||
final private int _bufferSize;
|
||||
final private Buffers _buffers;
|
||||
final private int _maxBuffers=-1;
|
||||
|
||||
|
||||
public WebSocketBuffers(final int bufferSize)
|
||||
{
|
||||
_bufferSize=bufferSize;
|
||||
_buffers = BuffersFactory.newBuffers(Type.DIRECT,bufferSize,Type.INDIRECT,bufferSize,Type.INDIRECT,_maxBuffers);
|
||||
_buffers = BuffersFactory.newBuffers(Type.DIRECT,bufferSize,Type.INDIRECT,bufferSize,Type.INDIRECT,-1);
|
||||
}
|
||||
|
||||
|
||||
public Buffer getBuffer()
|
||||
{
|
||||
return _buffers.getBuffer();
|
||||
}
|
||||
|
||||
|
||||
public Buffer getDirectBuffer()
|
||||
{
|
||||
return _buffers.getHeader();
|
||||
}
|
||||
|
||||
|
||||
public void returnBuffer(Buffer buffer)
|
||||
{
|
||||
_buffers.returnBuffer(buffer);
|
||||
|
|
|
@ -262,7 +262,7 @@ public class WebSocketClient
|
|||
/**
|
||||
* Set the initial maximum binary message size for a connection. This can be changed by
|
||||
* the application calling {@link WebSocket.Connection#setMaxBinaryMessageSize(int)}.
|
||||
* @param maxTextMessageSize The default maximum binary message size (in bytes) for a connection
|
||||
* @param maxBinaryMessageSize The default maximum binary message size (in bytes) for a connection
|
||||
*/
|
||||
public void setMaxBinaryMessageSize(int maxBinaryMessageSize)
|
||||
{
|
||||
|
@ -381,20 +381,21 @@ public class WebSocketClient
|
|||
{
|
||||
connection.getConnection().setMaxTextMessageSize(_maxTextMessageSize);
|
||||
connection.getConnection().setMaxBinaryMessageSize(_maxBinaryMessageSize);
|
||||
|
||||
|
||||
WebSocketConnection con;
|
||||
synchronized (this)
|
||||
{
|
||||
if (_channel!=null)
|
||||
_connection=connection;
|
||||
con=_connection;
|
||||
}
|
||||
|
||||
if (_connection!=null)
|
||||
if (con!=null)
|
||||
{
|
||||
if (_websocket instanceof WebSocket.OnFrame)
|
||||
((WebSocket.OnFrame)_websocket).onHandshake((WebSocket.FrameConnection)connection.getConnection());
|
||||
|
||||
_websocket.onOpen(connection.getConnection());
|
||||
((WebSocket.OnFrame)_websocket).onHandshake((WebSocket.FrameConnection)con.getConnection());
|
||||
|
||||
_websocket.onOpen(con.getConnection());
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -320,34 +320,41 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
|
||||
String origin = future.getOrigin();
|
||||
|
||||
String request=
|
||||
"GET "+path+" HTTP/1.1\r\n"+
|
||||
"Host: "+future.getURI().getHost()+":"+_future.getURI().getPort()+"\r\n"+
|
||||
"Upgrade: websocket\r\n"+
|
||||
"Connection: Upgrade\r\n"+
|
||||
"Sec-WebSocket-Key: "+_key+"\r\n"+
|
||||
(origin==null?"":"Origin: "+origin+"\r\n")+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n";
|
||||
StringBuilder request = new StringBuilder(512);
|
||||
request
|
||||
.append("GET ").append(path).append(" HTTP/1.1\r\n")
|
||||
.append("Host: ").append(future.getURI().getHost()).append(":").append(_future.getURI().getPort()).append("\r\n")
|
||||
.append("Upgrade: websocket\r\n")
|
||||
.append("Connection: Upgrade\r\n")
|
||||
.append("Sec-WebSocket-Key: ")
|
||||
.append(_key).append("\r\n");
|
||||
|
||||
if(origin!=null)
|
||||
request.append("Origin: ").append(origin).append("\r\n");
|
||||
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionD13.VERSION).append("\r\n");
|
||||
|
||||
if (future.getProtocol()!=null)
|
||||
request+="Sec-WebSocket-Protocol: "+future.getProtocol()+"\r\n";
|
||||
request.append("Sec-WebSocket-Protocol: ").append(future.getProtocol()).append("\r\n");
|
||||
|
||||
if (future.getCookies()!=null && future.getCookies().size()>0)
|
||||
{
|
||||
for (String cookie : future.getCookies().keySet())
|
||||
request+="Cookie: "+QuotedStringTokenizer.quoteIfNeeded(cookie,HttpFields.__COOKIE_DELIM)+
|
||||
"="+
|
||||
QuotedStringTokenizer.quoteIfNeeded(future.getCookies().get(cookie),HttpFields.__COOKIE_DELIM)+
|
||||
"\r\n";
|
||||
request
|
||||
.append("Cookie: ")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookie,HttpFields.__COOKIE_DELIM))
|
||||
.append("=")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(future.getCookies().get(cookie),HttpFields.__COOKIE_DELIM))
|
||||
.append("\r\n");
|
||||
}
|
||||
|
||||
request+="\r\n";
|
||||
request.append("\r\n");
|
||||
|
||||
// TODO extensions
|
||||
|
||||
try
|
||||
{
|
||||
Buffer handshake = new ByteArrayBuffer(request,false);
|
||||
Buffer handshake = new ByteArrayBuffer(request.toString(),false);
|
||||
int len=handshake.length();
|
||||
if (len!=_endp.flush(handshake))
|
||||
throw new IOException("incomplete");
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -18,10 +18,10 @@ import java.security.MessageDigest;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -30,8 +30,8 @@ import org.eclipse.jetty.io.Connection;
|
|||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.WebSocket.OnFrame;
|
||||
|
@ -51,21 +51,21 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
String _key1;
|
||||
String _key2;
|
||||
ByteArrayBuffer _hixieBytes;
|
||||
|
||||
|
||||
public WebSocketConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
{
|
||||
super(endpoint,timestamp);
|
||||
if (endpoint instanceof AsyncEndPoint)
|
||||
((AsyncEndPoint)endpoint).cancelIdle();
|
||||
|
||||
|
||||
_endp.setMaxIdleTime(maxIdleTime);
|
||||
|
||||
|
||||
_websocket = websocket;
|
||||
_protocol=protocol;
|
||||
|
||||
_generator = new WebSocketGeneratorD00(buffers, _endp);
|
||||
_parser = new WebSocketParserD00(buffers, endpoint, new FrameHandlerD0(_websocket));
|
||||
_parser = new WebSocketParserD00(buffers, endpoint, new FrameHandlerD00(_websocket));
|
||||
|
||||
if (_endp instanceof SelectChannelEndPoint)
|
||||
{
|
||||
|
@ -112,8 +112,8 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
// handle stupid hixie random bytes
|
||||
if (_hixieBytes!=null)
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
// take any available bytes from the parser buffer, which may have already been read
|
||||
Buffer buffer=_parser.getBuffer();
|
||||
if (buffer!=null && buffer.length()>0)
|
||||
|
@ -124,7 +124,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
_hixieBytes.put(buffer.peek(buffer.getIndex(),l));
|
||||
buffer.skip(l);
|
||||
}
|
||||
|
||||
|
||||
// while we are not blocked
|
||||
while(_endp.isOpen())
|
||||
{
|
||||
|
@ -154,7 +154,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
_websocket.onOpen(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// handle the framing protocol
|
||||
boolean progress=true;
|
||||
|
||||
|
@ -195,7 +195,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
_endp.close();
|
||||
else
|
||||
checkWriteable();
|
||||
|
||||
|
||||
checkWriteable();
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void doTheHixieHixieShake()
|
||||
{
|
||||
{
|
||||
byte[] result=WebSocketConnectionD00.doTheHixieHixieShake(
|
||||
WebSocketConnectionD00.hixieCrypt(_key1),
|
||||
WebSocketConnectionD00.hixieCrypt(_key2),
|
||||
|
@ -334,12 +334,12 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
public static byte[] doTheHixieHixieShake(long key1,long key2,byte[] key3)
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte [] fodder = new byte[16];
|
||||
|
||||
|
||||
fodder[0]=(byte)(0xff&(key1>>24));
|
||||
fodder[1]=(byte)(0xff&(key1>>16));
|
||||
fodder[2]=(byte)(0xff&(key1>>8));
|
||||
|
@ -348,11 +348,9 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
fodder[5]=(byte)(0xff&(key2>>16));
|
||||
fodder[6]=(byte)(0xff&(key2>>8));
|
||||
fodder[7]=(byte)(0xff&key2);
|
||||
for (int i=0;i<8;i++)
|
||||
fodder[8+i]=key3[i];
|
||||
System.arraycopy(key3, 0, fodder, 8, 8);
|
||||
md.update(fodder);
|
||||
byte[] result=md.digest();
|
||||
return result;
|
||||
return md.digest();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
|
@ -371,14 +369,18 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
String query=request.getQueryString();
|
||||
if (query!=null && query.length()>0)
|
||||
uri+="?"+query;
|
||||
uri=new HttpURI(uri).toString();
|
||||
String host=request.getHeader("Host");
|
||||
|
||||
|
||||
String origin=request.getHeader("Sec-WebSocket-Origin");
|
||||
if (origin==null)
|
||||
origin=request.getHeader("Origin");
|
||||
|
||||
if (origin!=null)
|
||||
origin= QuotedStringTokenizer.quoteIfNeeded(origin, "\r\n");
|
||||
|
||||
|
||||
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
||||
|
||||
|
||||
if (key1!=null)
|
||||
{
|
||||
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
||||
|
@ -413,7 +415,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
}
|
||||
|
||||
public void setMaxIdleTime(int ms)
|
||||
public void setMaxIdleTime(int ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -424,7 +426,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setMaxBinaryMessageSize(int size)
|
||||
{
|
||||
}
|
||||
|
@ -448,23 +450,22 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _protocol;
|
||||
}
|
||||
|
||||
class FrameHandlerD0 implements WebSocketParser.FrameHandler
|
||||
|
||||
static class FrameHandlerD00 implements WebSocketParser.FrameHandler
|
||||
{
|
||||
final WebSocket _websocket;
|
||||
final Utf8StringBuilder _utf8 = new Utf8StringBuilder();
|
||||
|
||||
FrameHandlerD0(WebSocket websocket)
|
||||
FrameHandlerD00(WebSocket websocket)
|
||||
{
|
||||
_websocket=websocket;
|
||||
}
|
||||
|
||||
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] array=buffer.array();
|
||||
|
||||
|
||||
if (opcode==0)
|
||||
{
|
||||
if (_websocket instanceof WebSocket.OnTextMessage)
|
||||
|
@ -485,10 +486,9 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
LOG.warn(th);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void close(int code,String message)
|
||||
{
|
||||
close(code,message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -18,7 +18,6 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.security.MessageDigest;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -49,18 +48,18 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
final static byte OP_PONG = 0x03;
|
||||
final static byte OP_TEXT = 0x04;
|
||||
final static byte OP_BINARY = 0x05;
|
||||
|
||||
|
||||
final static int CLOSE_NORMAL=1000;
|
||||
final static int CLOSE_SHUTDOWN=1001;
|
||||
final static int CLOSE_PROTOCOL=1002;
|
||||
final static int CLOSE_BADDATA=1003;
|
||||
final static int CLOSE_LARGE=1004;
|
||||
|
||||
|
||||
static boolean isLastFrame(int flags)
|
||||
{
|
||||
return (flags&0x8)!=0;
|
||||
}
|
||||
|
||||
|
||||
static boolean isControlFrame(int opcode)
|
||||
{
|
||||
switch(opcode)
|
||||
|
@ -73,8 +72,8 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private final static byte[] MAGIC;
|
||||
private final IdleCheck _idle;
|
||||
private final WebSocketParser _parser;
|
||||
|
@ -85,8 +84,8 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
private final OnTextMessage _onTextMessage;
|
||||
private final OnControl _onControl;
|
||||
private final String _protocol;
|
||||
private boolean _closedIn;
|
||||
private boolean _closedOut;
|
||||
private volatile boolean _closedIn;
|
||||
private volatile boolean _closedOut;
|
||||
private int _maxTextMessageSize;
|
||||
private int _maxBinaryMessageSize=-1;
|
||||
|
||||
|
@ -101,27 +100,26 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new FrameHandlerD06();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
private final WebSocket.FrameConnection _connection = new FrameConnectionD06();
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD06(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
{
|
||||
super(endpoint,timestamp);
|
||||
|
||||
// TODO - can we use the endpoint idle mechanism?
|
||||
|
||||
if (endpoint instanceof AsyncEndPoint)
|
||||
((AsyncEndPoint)endpoint).cancelIdle();
|
||||
|
||||
|
||||
_endp.setMaxIdleTime(maxIdleTime);
|
||||
|
||||
|
||||
_webSocket = websocket;
|
||||
_onFrame=_webSocket instanceof OnFrame ? (OnFrame)_webSocket : null;
|
||||
_onTextMessage=_webSocket instanceof OnTextMessage ? (OnTextMessage)_webSocket : null;
|
||||
|
@ -131,7 +129,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
_parser = new WebSocketParserD06(buffers, endpoint, _frameHandler,true);
|
||||
_protocol=protocol;
|
||||
|
||||
// TODO should these be AsyncEndPoint checks/calls?
|
||||
if (_endp instanceof SelectChannelEndPoint)
|
||||
{
|
||||
final SelectChannelEndPoint scep=(SelectChannelEndPoint)_endp;
|
||||
|
@ -153,8 +150,8 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{}
|
||||
};
|
||||
}
|
||||
|
||||
_maxTextMessageSize=buffers.getBufferSize();
|
||||
|
||||
_maxTextMessageSize=buffers.getBufferSize();
|
||||
_maxBinaryMessageSize=-1;
|
||||
}
|
||||
|
||||
|
@ -163,7 +160,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _connection;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
|
@ -178,7 +175,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
int filled=_parser.parseNext();
|
||||
|
||||
progress = flushed>0 || filled>0;
|
||||
|
||||
|
||||
if (filled<0 || flushed<0)
|
||||
{
|
||||
_endp.close();
|
||||
|
@ -210,7 +207,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
else
|
||||
checkWriteable();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -248,7 +245,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
_endp.close();
|
||||
else
|
||||
else
|
||||
closeOut(code,message);
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -269,7 +266,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedIn || _closedOut)
|
||||
_endp.close();
|
||||
else
|
||||
else
|
||||
{
|
||||
if (code<=0)
|
||||
code=WebSocketConnectionD06.CLOSE_NORMAL;
|
||||
|
@ -279,7 +276,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_CLOSE,bytes,0,bytes.length);
|
||||
}
|
||||
_generator.flush();
|
||||
|
||||
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
|
@ -388,7 +385,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setMaxIdleTime(int ms)
|
||||
public void setMaxIdleTime(int ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -459,7 +456,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return 0x8;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isControl(byte opcode)
|
||||
{
|
||||
|
@ -535,14 +532,14 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
{
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
synchronized(WebSocketConnectionD06.this)
|
||||
{
|
||||
// Ignore incoming after a close
|
||||
if (_closedIn)
|
||||
return;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
byte[] array=buffer.array();
|
||||
|
@ -553,13 +550,13 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
if (_onFrame.onFrame(flags,opcode,array,buffer.getIndex(),buffer.length()))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_onControl!=null && isControlFrame(opcode))
|
||||
{
|
||||
if (_onControl.onControl(opcode,array,buffer.getIndex(),buffer.length()))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch(opcode)
|
||||
{
|
||||
case WebSocketConnectionD06.OP_CONTINUATION:
|
||||
|
@ -583,7 +580,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
_connection.close(WebSocketConnectionD06.CLOSE_LARGE,"Text message size > "+_connection.getMaxTextMessageSize()+" chars");
|
||||
_utf8.reset();
|
||||
_opcode=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_opcode>=0 && _connection.getMaxBinaryMessageSize()>=0)
|
||||
{
|
||||
|
@ -652,7 +649,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
// Deliver the message
|
||||
_onTextMessage.onMessage(buffer.toString(StringUtil.__UTF8));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (_connection.getMaxTextMessageSize()>=0)
|
||||
{
|
||||
|
@ -662,7 +659,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
else
|
||||
{
|
||||
_utf8.reset();
|
||||
_opcode=-1;
|
||||
_opcode=-1;
|
||||
_connection.close(WebSocketConnectionD06.CLOSE_LARGE,"Text message size > "+_connection.getMaxTextMessageSize()+" chars");
|
||||
}
|
||||
}
|
||||
|
@ -679,7 +676,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
_onBinaryMessage.onMessage(array,buffer.getIndex(),buffer.length());
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (_connection.getMaxBinaryMessageSize()>=0)
|
||||
{
|
||||
|
@ -700,7 +697,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(ThreadDeath th)
|
||||
|
@ -734,12 +731,8 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri=request.getRequestURI();
|
||||
String query=request.getQueryString();
|
||||
if (query!=null && query.length()>0)
|
||||
uri+="?"+query;
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -18,7 +18,6 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.security.MessageDigest;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -53,7 +52,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
final static byte OP_PING = 0x09;
|
||||
final static byte OP_PONG = 0x0A;
|
||||
final static byte OP_EXT_CTRL = 0x0B;
|
||||
|
||||
|
||||
final static int CLOSE_NORMAL=1000;
|
||||
final static int CLOSE_SHUTDOWN=1001;
|
||||
final static int CLOSE_PROTOCOL=1002;
|
||||
|
@ -61,21 +60,21 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
final static int CLOSE_NOCODE=1005;
|
||||
final static int CLOSE_NOCLOSE=1006;
|
||||
final static int CLOSE_NOTUTF8=1007;
|
||||
|
||||
|
||||
final static int FLAG_FIN=0x8;
|
||||
|
||||
|
||||
final static int VERSION=8;
|
||||
|
||||
|
||||
static boolean isLastFrame(byte flags)
|
||||
{
|
||||
return (flags&FLAG_FIN)!=0;
|
||||
}
|
||||
|
||||
|
||||
static boolean isControlFrame(byte opcode)
|
||||
{
|
||||
return (opcode&OP_CONTROL)!=0;
|
||||
}
|
||||
|
||||
|
||||
private final static byte[] MAGIC;
|
||||
private final IdleCheck _idle;
|
||||
private final List<Extension> _extensions;
|
||||
|
@ -97,7 +96,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
private volatile boolean _closedOut;
|
||||
private int _maxTextMessageSize=-1;
|
||||
private int _maxBinaryMessageSize=-1;
|
||||
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
|
@ -109,11 +108,11 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
|
||||
|
||||
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD12(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft)
|
||||
|
@ -121,28 +120,28 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
this(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,null);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD12(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft, MaskGen maskgen)
|
||||
throws IOException
|
||||
{
|
||||
super(endpoint,timestamp);
|
||||
|
||||
|
||||
_context=Thread.currentThread().getContextClassLoader();
|
||||
|
||||
|
||||
if (endpoint instanceof AsyncEndPoint)
|
||||
((AsyncEndPoint)endpoint).cancelIdle();
|
||||
|
||||
|
||||
_draft=draft;
|
||||
_endp.setMaxIdleTime(maxIdleTime);
|
||||
|
||||
|
||||
_webSocket = websocket;
|
||||
_onFrame=_webSocket instanceof OnFrame ? (OnFrame)_webSocket : null;
|
||||
_onTextMessage=_webSocket instanceof OnTextMessage ? (OnTextMessage)_webSocket : null;
|
||||
_onBinaryMessage=_webSocket instanceof OnBinaryMessage ? (OnBinaryMessage)_webSocket : null;
|
||||
_onControl=_webSocket instanceof OnControl ? (OnControl)_webSocket : null;
|
||||
_generator = new WebSocketGeneratorD12(buffers, _endp,maskgen);
|
||||
|
||||
|
||||
_extensions=extensions;
|
||||
if (_extensions!=null)
|
||||
{
|
||||
|
@ -159,12 +158,11 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
|
||||
_outbound=(_extensions==null||_extensions.size()==0)?_generator:extensions.get(extensions.size()-1);
|
||||
_inbound=(_extensions==null||_extensions.size()==0)?_frameHandler:extensions.get(0);
|
||||
|
||||
|
||||
_parser = new WebSocketParserD12(buffers, endpoint,_inbound,maskgen==null);
|
||||
|
||||
|
||||
_protocol=protocol;
|
||||
|
||||
// TODO should these be AsyncEndPoint checks/calls?
|
||||
if (_endp instanceof SelectChannelEndPoint)
|
||||
{
|
||||
final SelectChannelEndPoint scep=(SelectChannelEndPoint)_endp;
|
||||
|
@ -193,16 +191,16 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _connection;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public List<Extension> getExtensions()
|
||||
{
|
||||
if (_extensions==null)
|
||||
return Collections.emptyList();
|
||||
|
||||
|
||||
return _extensions;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
|
@ -220,7 +218,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
int filled=_parser.parseNext();
|
||||
|
||||
progress = flushed>0 || filled>0;
|
||||
|
||||
|
||||
if (filled<0 || flushed<0)
|
||||
{
|
||||
_endp.close();
|
||||
|
@ -297,7 +295,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
public void closeIn(int code,String message)
|
||||
{
|
||||
LOG.debug("ClosedIn {} {}",this,message);
|
||||
|
||||
|
||||
final boolean closedOut;
|
||||
final boolean closed;
|
||||
synchronized (this)
|
||||
|
@ -323,7 +321,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (closedOut)
|
||||
_endp.close();
|
||||
else
|
||||
else
|
||||
closeOut(code,message);
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -337,7 +335,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
public void closeOut(int code,String message)
|
||||
{
|
||||
LOG.debug("ClosedOut {} {}",this,message);
|
||||
|
||||
|
||||
final boolean close;
|
||||
final boolean closed;
|
||||
synchronized (this)
|
||||
|
@ -351,7 +349,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
_closeMessage=message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (closed)
|
||||
|
@ -363,7 +361,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (close)
|
||||
_endp.close();
|
||||
else
|
||||
else
|
||||
{
|
||||
if (code<=0)
|
||||
code=WebSocketConnectionD12.CLOSE_NORMAL;
|
||||
|
@ -467,7 +465,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setMaxIdleTime(int ms)
|
||||
public void setMaxIdleTime(int ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -496,7 +494,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _endp.getMaxIdleTime();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getMaxTextMessageSize()
|
||||
{
|
||||
|
@ -538,7 +536,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return FLAG_FIN;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isControl(byte opcode)
|
||||
{
|
||||
|
@ -586,7 +584,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
close(CLOSE_NORMAL,null);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setAllowFrameFragmentation(boolean allowFragmentation)
|
||||
{
|
||||
|
@ -618,8 +616,8 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
|
||||
public void onFrame(final byte flags, final byte opcode, final Buffer buffer)
|
||||
{
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
synchronized(WebSocketConnectionD12.this)
|
||||
{
|
||||
// Ignore incoming after a close
|
||||
|
@ -664,7 +662,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
else
|
||||
textMessageTooLarge();
|
||||
}
|
||||
|
||||
|
||||
if (_opcode>=0 && _connection.getMaxBinaryMessageSize()>=0)
|
||||
{
|
||||
if (checkBinaryMessageSize(_aggregate.length(),buffer.length()))
|
||||
|
@ -762,7 +760,6 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
else if (_connection.getMaxBinaryMessageSize()>=0)
|
||||
{
|
||||
_opcode=opcode;
|
||||
// TODO use a growing buffer rather than a fixed one.
|
||||
if (_aggregate==null)
|
||||
_aggregate=new ByteArrayBuffer(_connection.getMaxBinaryMessageSize());
|
||||
_aggregate.put(buffer);
|
||||
|
@ -773,7 +770,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
_connection.close(WebSocketConnectionD12.CLOSE_BADDATA,"Binary frame aggregation disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(ThreadDeath th)
|
||||
|
@ -800,7 +797,7 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void textMessageTooLarge()
|
||||
{
|
||||
LOG.warn("Text message too large > {} chars for {}",_connection.getMaxTextMessageSize(),_endp);
|
||||
|
@ -833,23 +830,19 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri=request.getRequestURI();
|
||||
String query=request.getQueryString();
|
||||
if (query!=null && query.length()>0)
|
||||
uri+="?"+query;
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
|
||||
response.setHeader("Upgrade", "WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
|
||||
|
||||
for(Extension ext : _extensions)
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -18,7 +18,6 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.security.MessageDigest;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -31,6 +30,7 @@ import org.eclipse.jetty.io.EndPoint;
|
|||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8Appendable;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -53,7 +53,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
final static byte OP_PING = 0x09;
|
||||
final static byte OP_PONG = 0x0A;
|
||||
final static byte OP_EXT_CTRL = 0x0B;
|
||||
|
||||
|
||||
final static int CLOSE_NORMAL=1000;
|
||||
final static int CLOSE_SHUTDOWN=1001;
|
||||
final static int CLOSE_PROTOCOL=1002;
|
||||
|
@ -65,26 +65,25 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
final static int CLOSE_POLICY_VIOLATION=1008;
|
||||
final static int CLOSE_MESSAGE_TOO_LARGE=1009;
|
||||
final static int CLOSE_REQUIRED_EXTENSION=1010;
|
||||
|
||||
|
||||
final static int FLAG_FIN=0x8;
|
||||
|
||||
|
||||
final static int VERSION=13;
|
||||
|
||||
|
||||
static boolean isLastFrame(byte flags)
|
||||
{
|
||||
return (flags&FLAG_FIN)!=0;
|
||||
}
|
||||
|
||||
|
||||
static boolean isControlFrame(byte opcode)
|
||||
{
|
||||
return (opcode&OP_CONTROL)!=0;
|
||||
}
|
||||
|
||||
|
||||
private final static byte[] MAGIC;
|
||||
private final IdleCheck _idle;
|
||||
private final List<Extension> _extensions;
|
||||
private final WebSocketParserD13 _parser;
|
||||
private final WebSocketParser.FrameHandler _inbound;
|
||||
private final WebSocketGeneratorD13 _generator;
|
||||
private final WebSocketGenerator _outbound;
|
||||
private final WebSocket _webSocket;
|
||||
|
@ -101,7 +100,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
private volatile boolean _closedOut;
|
||||
private int _maxTextMessageSize=-1;
|
||||
private int _maxBinaryMessageSize=-1;
|
||||
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
|
@ -113,11 +112,9 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
|
||||
|
||||
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft)
|
||||
|
@ -125,29 +122,30 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
this(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,null);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft, MaskGen maskgen)
|
||||
throws IOException
|
||||
{
|
||||
super(endpoint,timestamp);
|
||||
|
||||
|
||||
_context=Thread.currentThread().getContextClassLoader();
|
||||
|
||||
|
||||
if (endpoint instanceof AsyncEndPoint)
|
||||
((AsyncEndPoint)endpoint).cancelIdle();
|
||||
|
||||
|
||||
_draft=draft;
|
||||
_endp.setMaxIdleTime(maxIdleTime);
|
||||
|
||||
|
||||
_webSocket = websocket;
|
||||
_onFrame=_webSocket instanceof OnFrame ? (OnFrame)_webSocket : null;
|
||||
_onTextMessage=_webSocket instanceof OnTextMessage ? (OnTextMessage)_webSocket : null;
|
||||
_onBinaryMessage=_webSocket instanceof OnBinaryMessage ? (OnBinaryMessage)_webSocket : null;
|
||||
_onControl=_webSocket instanceof OnControl ? (OnControl)_webSocket : null;
|
||||
_generator = new WebSocketGeneratorD13(buffers, _endp,maskgen);
|
||||
|
||||
|
||||
_extensions=extensions;
|
||||
WebSocketParser.FrameHandler frameHandler = new WSFrameHandler();
|
||||
if (_extensions!=null)
|
||||
{
|
||||
int e=0;
|
||||
|
@ -155,17 +153,17 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
extension.bind(
|
||||
_connection,
|
||||
e==extensions.size()-1?_frameHandler:extensions.get(e+1),
|
||||
e==extensions.size()-1? frameHandler :extensions.get(e+1),
|
||||
e==0?_generator:extensions.get(e-1));
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
_outbound=(_extensions==null||_extensions.size()==0)?_generator:extensions.get(extensions.size()-1);
|
||||
_inbound=(_extensions==null||_extensions.size()==0)?_frameHandler:extensions.get(0);
|
||||
|
||||
_parser = new WebSocketParserD13(buffers, endpoint,_inbound,maskgen==null);
|
||||
|
||||
WebSocketParser.FrameHandler inbound = (_extensions == null || _extensions.size() == 0) ? frameHandler : extensions.get(0);
|
||||
|
||||
_parser = new WebSocketParserD13(buffers, endpoint, inbound,maskgen==null);
|
||||
|
||||
_protocol=protocol;
|
||||
|
||||
// TODO should these be AsyncEndPoint checks/calls?
|
||||
|
@ -197,16 +195,16 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _connection;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public List<Extension> getExtensions()
|
||||
{
|
||||
if (_extensions==null)
|
||||
return Collections.emptyList();
|
||||
|
||||
|
||||
return _extensions;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
|
@ -224,7 +222,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
int filled=_parser.parseNext();
|
||||
|
||||
progress = flushed>0 || filled>0;
|
||||
|
||||
|
||||
if (filled<0 || flushed<0)
|
||||
{
|
||||
_endp.close();
|
||||
|
@ -301,15 +299,15 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
public void closeIn(int code,String message)
|
||||
{
|
||||
LOG.debug("ClosedIn {} {}",this,message);
|
||||
|
||||
final boolean closedOut;
|
||||
final boolean closed;
|
||||
|
||||
final boolean close;
|
||||
final boolean tell_app;
|
||||
synchronized (this)
|
||||
{
|
||||
closedOut=_closedOut;
|
||||
close=_closedOut;
|
||||
_closedIn=true;
|
||||
closed=_closeCode==0;
|
||||
if (closed)
|
||||
tell_app=_closeCode==0;
|
||||
if (tell_app)
|
||||
{
|
||||
_closeCode=code;
|
||||
_closeMessage=message;
|
||||
|
@ -318,16 +316,16 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
|
||||
try
|
||||
{
|
||||
if (closed)
|
||||
if (tell_app)
|
||||
_webSocket.onClose(code,message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (closedOut)
|
||||
if (close)
|
||||
_endp.close();
|
||||
else
|
||||
else
|
||||
closeOut(code,message);
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -341,33 +339,33 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
public void closeOut(int code,String message)
|
||||
{
|
||||
LOG.debug("ClosedOut {} {}",this,message);
|
||||
|
||||
|
||||
final boolean close;
|
||||
final boolean closed;
|
||||
final boolean tell_app;
|
||||
final boolean send_close;
|
||||
synchronized (this)
|
||||
{
|
||||
close=_closedIn || _closedOut;
|
||||
close=_closedIn;
|
||||
send_close=!_closedOut;
|
||||
_closedOut=true;
|
||||
closed=_closeCode==0;
|
||||
if (closed)
|
||||
tell_app=_closeCode==0;
|
||||
if (tell_app)
|
||||
{
|
||||
_closeCode=code;
|
||||
_closeMessage=message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (closed)
|
||||
if (tell_app)
|
||||
_webSocket.onClose(code,message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (close)
|
||||
_endp.close();
|
||||
else
|
||||
if (send_close)
|
||||
{
|
||||
if (code<=0)
|
||||
code=WebSocketConnectionD13.CLOSE_NORMAL;
|
||||
|
@ -375,8 +373,12 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
bytes[0]=(byte)(code/0x100);
|
||||
bytes[1]=(byte)(code%0x100);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD13.OP_CLOSE,bytes,0,bytes.length);
|
||||
_outbound.flush();
|
||||
if (close)
|
||||
_endp.shutdownOutput();
|
||||
}
|
||||
_outbound.flush();
|
||||
else if (close)
|
||||
_endp.close();
|
||||
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -471,7 +473,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setMaxIdleTime(int ms)
|
||||
public void setMaxIdleTime(int ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -500,7 +502,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _endp.getMaxIdleTime();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getMaxTextMessageSize()
|
||||
{
|
||||
|
@ -542,7 +544,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return FLAG_FIN;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isControl(byte opcode)
|
||||
{
|
||||
|
@ -590,7 +592,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
close(CLOSE_NORMAL,null);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setAllowFrameFragmentation(boolean allowFragmentation)
|
||||
{
|
||||
|
@ -622,8 +624,8 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
|
||||
public void onFrame(final byte flags, final byte opcode, final Buffer buffer)
|
||||
{
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
synchronized(WebSocketConnectionD13.this)
|
||||
{
|
||||
// Ignore incoming after a close
|
||||
|
@ -668,7 +670,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
else
|
||||
textMessageTooLarge();
|
||||
}
|
||||
|
||||
|
||||
if (_opcode>=0 && _connection.getMaxBinaryMessageSize()>=0)
|
||||
{
|
||||
if (checkBinaryMessageSize(_aggregate.length(),buffer.length()))
|
||||
|
@ -712,7 +714,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
String message=null;
|
||||
if (buffer.length()>=2)
|
||||
{
|
||||
code=buffer.array()[buffer.getIndex()]*0x100+buffer.array()[buffer.getIndex()+1];
|
||||
code=(0xff&buffer.array()[buffer.getIndex()])*0x100+(0xff&buffer.array()[buffer.getIndex()+1]);
|
||||
if (buffer.length()>2)
|
||||
message=new String(buffer.array(),buffer.getIndex()+2,buffer.length()-2,StringUtil.__UTF8);
|
||||
}
|
||||
|
@ -777,9 +779,15 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
_connection.close(WebSocketConnectionD13.CLOSE_POLICY_VIOLATION,"Binary frame aggregation disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Utf8Appendable.NotUtf8Exception notUtf8)
|
||||
{
|
||||
LOG.warn("{} for {}",notUtf8,_endp);
|
||||
LOG.debug(notUtf8);
|
||||
_connection.close(WebSocketConnectionD13.CLOSE_NOT_UTF8,"Invalid UTF-8");
|
||||
}
|
||||
catch(ThreadDeath th)
|
||||
{
|
||||
throw th;
|
||||
|
@ -804,7 +812,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void textMessageTooLarge()
|
||||
{
|
||||
LOG.warn("Text message too large > {} chars for {}",_connection.getMaxTextMessageSize(),_endp);
|
||||
|
@ -837,23 +845,19 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri=request.getRequestURI();
|
||||
String query=request.getQueryString();
|
||||
if (query!=null && query.length()>0)
|
||||
uri+="?"+query;
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
|
||||
|
||||
for(Extension ext : _extensions)
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -43,16 +42,19 @@ public class WebSocketFactory
|
|||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param request
|
||||
* @param protocol
|
||||
* @returns
|
||||
* <p>Factory method that applications needs to implement to return a
|
||||
* {@link WebSocket} object.</p>
|
||||
* @param request the incoming HTTP upgrade request
|
||||
* @param protocol the websocket sub protocol
|
||||
* @return a new {@link WebSocket} object that will handle websocket events.
|
||||
*/
|
||||
WebSocket doWebSocketConnect(HttpServletRequest request, String protocol);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Check the origin of an incoming WebSocket handshake request
|
||||
* @param request
|
||||
* @param origin
|
||||
/**
|
||||
* <p>Checks the origin of an incoming WebSocket handshake request.</p>
|
||||
* @param request the incoming HTTP upgrade request
|
||||
* @param origin the origin URI
|
||||
* @return boolean to indicate that the origin is acceptable.
|
||||
*/
|
||||
boolean checkOrigin(HttpServletRequest request, String origin);
|
||||
|
@ -64,7 +66,7 @@ public class WebSocketFactory
|
|||
_extensionClasses.put("fragment",FragmentExtension.class);
|
||||
_extensionClasses.put("x-deflate-frame",DeflateFrameExtension.class);
|
||||
}
|
||||
|
||||
|
||||
private final Acceptor _acceptor;
|
||||
private WebSocketBuffers _buffers;
|
||||
private int _maxIdleTime = 300000;
|
||||
|
@ -90,7 +92,7 @@ public class WebSocketFactory
|
|||
{
|
||||
return _extensionClasses;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the maxIdleTime.
|
||||
*
|
||||
|
@ -161,7 +163,7 @@ public class WebSocketFactory
|
|||
/**
|
||||
* Set the initial maximum binary message size for a connection. This can be changed by
|
||||
* the application calling {@link WebSocket.Connection#setMaxBinaryMessageSize(int)}.
|
||||
* @param maxTextMessageSize The default maximum binary message size (in bytes) for a connection
|
||||
* @param maxBinaryMessageSize The default maximum binary message size (in bytes) for a connection
|
||||
*/
|
||||
public void setMaxBinaryMessageSize(int maxBinaryMessageSize)
|
||||
{
|
||||
|
@ -201,7 +203,7 @@ public class WebSocketFactory
|
|||
while (tok.hasMoreTokens())
|
||||
extensions_requested.add(tok.nextToken());
|
||||
}
|
||||
|
||||
|
||||
final WebSocketConnection connection;
|
||||
final List<Extension> extensions;
|
||||
switch (draft)
|
||||
|
@ -215,16 +217,16 @@ public class WebSocketFactory
|
|||
extensions=Collections.emptyList();
|
||||
connection = new WebSocketConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD12.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketConnectionD12(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
case 13:
|
||||
case 13:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD13.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
|
@ -275,7 +277,7 @@ public class WebSocketFactory
|
|||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Try each requested protocol
|
||||
WebSocket websocket = null;
|
||||
String protocol = request.getHeader("Sec-WebSocket-Protocol");
|
||||
|
@ -305,7 +307,7 @@ public class WebSocketFactory
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public List<Extension> initExtensions(List<String> requested,int maxDataOpcodes,int maxControlOpcodes,int maxReservedBits)
|
||||
{
|
||||
List<Extension> extensions = new ArrayList<Extension>();
|
||||
|
@ -321,9 +323,9 @@ public class WebSocketFactory
|
|||
String value=nv.hasMoreTokens()?nv.nextToken().trim():null;
|
||||
parameters.put(name,value);
|
||||
}
|
||||
|
||||
|
||||
Extension extension = newExtension(extName);
|
||||
|
||||
|
||||
if (extension==null)
|
||||
continue;
|
||||
|
||||
|
@ -349,9 +351,9 @@ public class WebSocketFactory
|
|||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -149,8 +149,6 @@ public class WebSocketGeneratorD00 implements WebSocketGenerator
|
|||
{
|
||||
while (_buffer.space()==0)
|
||||
{
|
||||
// TODO: in case the I/O system signals write ready, but when we attempt to write we cannot
|
||||
// TODO: we should decrease the blockFor timeout instead of waiting again the whole timeout
|
||||
boolean ready = _endp.blockWritable(blockFor);
|
||||
if (!ready)
|
||||
throw new IOException("Write timeout");
|
||||
|
|
|
@ -4,18 +4,16 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -38,14 +36,14 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
private int _m;
|
||||
private boolean _opsent;
|
||||
private final MaskGen _maskGen;
|
||||
|
||||
|
||||
public WebSocketGeneratorD06(WebSocketBuffers buffers, EndPoint endp)
|
||||
{
|
||||
_buffers=buffers;
|
||||
_endp=endp;
|
||||
_maskGen=null;
|
||||
}
|
||||
|
||||
|
||||
public WebSocketGeneratorD06(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen)
|
||||
{
|
||||
_buffers=buffers;
|
||||
|
@ -56,22 +54,22 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
// System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);
|
||||
|
||||
|
||||
long blockFor=_endp.getMaxIdleTime();
|
||||
|
||||
|
||||
if (_buffer==null)
|
||||
_buffer=(_maskGen!=null)?_buffers.getBuffer():_buffers.getDirectBuffer();
|
||||
|
||||
|
||||
boolean last=WebSocketConnectionD06.isLastFrame(flags);
|
||||
opcode=(byte)(((0xf&flags)<<4)+0xf&opcode);
|
||||
|
||||
|
||||
int space=(_maskGen!=null)?14:10;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
opcode = _opsent?WebSocketConnectionD06.OP_CONTINUATION:opcode;
|
||||
_opsent=true;
|
||||
|
||||
|
||||
int payload=length;
|
||||
if (payload+space>_buffer.capacity())
|
||||
{
|
||||
|
@ -85,7 +83,7 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
// ensure there is space for header
|
||||
if (_buffer.space() <= space)
|
||||
expelBuffer(blockFor);
|
||||
|
||||
|
||||
// write mask
|
||||
if ((_maskGen!=null))
|
||||
{
|
||||
|
@ -100,10 +98,10 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
bufferPut(new byte[]{
|
||||
opcode,
|
||||
(byte)0x7f,
|
||||
(byte)((payload>>56)&0x7f),
|
||||
(byte)((payload>>48)&0xff),
|
||||
(byte)((payload>>40)&0xff),
|
||||
(byte)((payload>>32)&0xff),
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)((payload>>24)&0xff),
|
||||
(byte)((payload>>16)&0xff),
|
||||
(byte)((payload>>8)&0xff),
|
||||
|
@ -129,7 +127,7 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
{
|
||||
_buffer.compact();
|
||||
int chunk = remaining < _buffer.space() ? remaining : _buffer.space();
|
||||
|
||||
|
||||
if ((_maskGen!=null))
|
||||
{
|
||||
for (int i=0;i<chunk;i++)
|
||||
|
@ -137,7 +135,7 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
}
|
||||
else
|
||||
_buffer.put(content, offset + (payload - remaining), chunk);
|
||||
|
||||
|
||||
remaining -= chunk;
|
||||
if (_buffer.space() > 0)
|
||||
{
|
||||
|
@ -169,7 +167,7 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
data[i]^=_mask[+_m++%4];
|
||||
_buffer.put(data);
|
||||
}
|
||||
|
||||
|
||||
private synchronized void bufferPut(byte data) throws IOException
|
||||
{
|
||||
_buffer.put((byte)(data^_mask[+_m++%4]));
|
||||
|
@ -212,8 +210,6 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
{
|
||||
while (_buffer.space()==0)
|
||||
{
|
||||
// TODO: in case the I/O system signals write ready, but when we attempt to write we cannot
|
||||
// TODO: we should decrease the blockFor timeout instead of waiting again the whole timeout
|
||||
boolean ready = _endp.blockWritable(blockFor);
|
||||
if (!ready)
|
||||
throw new IOException("Write timeout");
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -43,7 +43,7 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
_endp=endp;
|
||||
_maskGen=null;
|
||||
}
|
||||
|
||||
|
||||
public WebSocketGeneratorD12(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen)
|
||||
{
|
||||
_buffers=buffers;
|
||||
|
@ -55,27 +55,26 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
// System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);
|
||||
|
||||
|
||||
boolean mask=_maskGen!=null;
|
||||
|
||||
|
||||
if (_buffer==null)
|
||||
_buffer=mask?_buffers.getBuffer():_buffers.getDirectBuffer();
|
||||
|
||||
|
||||
boolean last=WebSocketConnectionD12.isLastFrame(flags);
|
||||
byte orig=opcode;
|
||||
|
||||
|
||||
int space=mask?14:10;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
opcode = _opsent?WebSocketConnectionD12.OP_CONTINUATION:opcode;
|
||||
opcode=(byte)(((0xf&flags)<<4)+(0xf&opcode));
|
||||
_opsent=true;
|
||||
|
||||
|
||||
int payload=length;
|
||||
if (payload+space>_buffer.capacity())
|
||||
{
|
||||
|
@ -85,7 +84,7 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
}
|
||||
else if (last)
|
||||
opcode= (byte)(opcode|0x80); // Set the FIN bit
|
||||
|
||||
|
||||
// ensure there is space for header
|
||||
if (_buffer.space() <= space)
|
||||
{
|
||||
|
@ -93,17 +92,17 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
if (_buffer.space() <= space)
|
||||
flush();
|
||||
}
|
||||
|
||||
|
||||
// write the opcode and length
|
||||
if (payload>0xffff)
|
||||
{
|
||||
_buffer.put(new byte[]{
|
||||
opcode,
|
||||
mask?(byte)0xff:(byte)0x7f,
|
||||
(byte)((payload>>56)&0x7f),
|
||||
(byte)((payload>>48)&0xff),
|
||||
(byte)((payload>>40)&0xff),
|
||||
(byte)((payload>>32)&0xff),
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)((payload>>24)&0xff),
|
||||
(byte)((payload>>16)&0xff),
|
||||
(byte)((payload>>8)&0xff),
|
||||
|
@ -119,7 +118,7 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
}
|
||||
else
|
||||
{
|
||||
_buffer.put(new byte[]{
|
||||
_buffer.put(new byte[]{
|
||||
opcode,
|
||||
(byte)(mask?(0x80|payload):payload)});
|
||||
}
|
||||
|
@ -132,14 +131,14 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
_buffer.put(_mask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// write payload
|
||||
int remaining = payload;
|
||||
while (remaining > 0)
|
||||
{
|
||||
_buffer.compact();
|
||||
int chunk = remaining < _buffer.space() ? remaining : _buffer.space();
|
||||
|
||||
|
||||
if (mask)
|
||||
{
|
||||
for (int i=0;i<chunk;i++)
|
||||
|
@ -147,7 +146,7 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
}
|
||||
else
|
||||
_buffer.put(content, offset + (payload - remaining), chunk);
|
||||
|
||||
|
||||
remaining -= chunk;
|
||||
if (_buffer.space() > 0)
|
||||
{
|
||||
|
@ -170,7 +169,7 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
}
|
||||
while (length>0);
|
||||
_opsent=!last;
|
||||
|
||||
|
||||
if (_buffer!=null && _buffer.length()==0)
|
||||
{
|
||||
_buffers.returnBuffer(_buffer);
|
||||
|
@ -194,7 +193,7 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
|
|||
if (_buffer==null)
|
||||
return 0;
|
||||
int result = flushBuffer();
|
||||
|
||||
|
||||
if (!_endp.isBlocking())
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -43,7 +43,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
_endp=endp;
|
||||
_maskGen=null;
|
||||
}
|
||||
|
||||
|
||||
public WebSocketGeneratorD13(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen)
|
||||
{
|
||||
_buffers=buffers;
|
||||
|
@ -55,27 +55,26 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
// System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);
|
||||
|
||||
|
||||
boolean mask=_maskGen!=null;
|
||||
|
||||
|
||||
if (_buffer==null)
|
||||
_buffer=mask?_buffers.getBuffer():_buffers.getDirectBuffer();
|
||||
|
||||
|
||||
boolean last=WebSocketConnectionD13.isLastFrame(flags);
|
||||
byte orig=opcode;
|
||||
|
||||
|
||||
int space=mask?14:10;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
opcode = _opsent?WebSocketConnectionD13.OP_CONTINUATION:opcode;
|
||||
opcode=(byte)(((0xf&flags)<<4)+(0xf&opcode));
|
||||
_opsent=true;
|
||||
|
||||
|
||||
int payload=length;
|
||||
if (payload+space>_buffer.capacity())
|
||||
{
|
||||
|
@ -85,7 +84,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
}
|
||||
else if (last)
|
||||
opcode= (byte)(opcode|0x80); // Set the FIN bit
|
||||
|
||||
|
||||
// ensure there is space for header
|
||||
if (_buffer.space() <= space)
|
||||
{
|
||||
|
@ -93,17 +92,17 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
if (_buffer.space() <= space)
|
||||
flush();
|
||||
}
|
||||
|
||||
|
||||
// write the opcode and length
|
||||
if (payload>0xffff)
|
||||
{
|
||||
_buffer.put(new byte[]{
|
||||
opcode,
|
||||
mask?(byte)0xff:(byte)0x7f,
|
||||
(byte)((payload>>56)&0x7f),
|
||||
(byte)((payload>>48)&0xff),
|
||||
(byte)((payload>>40)&0xff),
|
||||
(byte)((payload>>32)&0xff),
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)0,
|
||||
(byte)((payload>>24)&0xff),
|
||||
(byte)((payload>>16)&0xff),
|
||||
(byte)((payload>>8)&0xff),
|
||||
|
@ -119,7 +118,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
}
|
||||
else
|
||||
{
|
||||
_buffer.put(new byte[]{
|
||||
_buffer.put(new byte[]{
|
||||
opcode,
|
||||
(byte)(mask?(0x80|payload):payload)});
|
||||
}
|
||||
|
@ -132,14 +131,14 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
_buffer.put(_mask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// write payload
|
||||
int remaining = payload;
|
||||
while (remaining > 0)
|
||||
{
|
||||
_buffer.compact();
|
||||
int chunk = remaining < _buffer.space() ? remaining : _buffer.space();
|
||||
|
||||
|
||||
if (mask)
|
||||
{
|
||||
for (int i=0;i<chunk;i++)
|
||||
|
@ -147,7 +146,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
}
|
||||
else
|
||||
_buffer.put(content, offset + (payload - remaining), chunk);
|
||||
|
||||
|
||||
remaining -= chunk;
|
||||
if (_buffer.space() > 0)
|
||||
{
|
||||
|
@ -170,7 +169,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
}
|
||||
while (length>0);
|
||||
_opsent=!last;
|
||||
|
||||
|
||||
if (_buffer!=null && _buffer.length()==0)
|
||||
{
|
||||
_buffers.returnBuffer(_buffer);
|
||||
|
@ -194,7 +193,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
if (_buffer==null)
|
||||
return 0;
|
||||
int result = flushBuffer();
|
||||
|
||||
|
||||
if (!_endp.isBlocking())
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -51,8 +51,8 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
* @param buffers The buffers to use for parsing. Only the {@link Buffers#getBuffer()} is used.
|
||||
* This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
|
||||
* is mostly used.
|
||||
* @param endp
|
||||
* @param handler
|
||||
* @param endp the endpoint
|
||||
* @param handler the handler to notify when a parse event occurs
|
||||
*/
|
||||
public WebSocketParserD00(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler)
|
||||
{
|
||||
|
@ -89,7 +89,6 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
int total_filled=0;
|
||||
|
||||
// Loop until an datagram call back or can't fill anymore
|
||||
boolean progress=true;
|
||||
while(true)
|
||||
{
|
||||
int length=_buffer.length();
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -31,9 +31,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class WebSocketParserD06 implements WebSocketParser
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketParserD06.class);
|
||||
|
||||
public enum State {
|
||||
|
||||
|
||||
public enum State {
|
||||
|
||||
START(0), MASK(4), OPCODE(1), LENGTH_7(1), LENGTH_16(2), LENGTH_63(8), DATA(0), SKIP(1);
|
||||
|
||||
int _needs;
|
||||
|
@ -47,7 +47,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
{
|
||||
return _needs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private final WebSocketBuffers _buffers;
|
||||
|
@ -68,8 +68,9 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
* @param buffers The buffers to use for parsing. Only the {@link Buffers#getBuffer()} is used.
|
||||
* This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
|
||||
* is mostly used.
|
||||
* @param endp
|
||||
* @param handler
|
||||
* @param endp the endpoint
|
||||
* @param handler the handler to notify when a parse event occurs
|
||||
* @param masked whether masking should be handled
|
||||
*/
|
||||
public WebSocketParserD06(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean masked)
|
||||
{
|
||||
|
@ -140,7 +141,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
}
|
||||
|
||||
// if we are here, then we have sufficient bytes to process the current state.
|
||||
|
||||
|
||||
// Parse the buffer byte by byte (unless it is STATE_DATA)
|
||||
byte b;
|
||||
while (_state!=State.DATA && available>=(_state==State.SKIP?1:_bytesNeeded))
|
||||
|
@ -151,7 +152,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
_state=_masked?State.MASK:State.OPCODE;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
continue;
|
||||
|
||||
|
||||
case MASK:
|
||||
_buffer.get(_mask,0,4);
|
||||
available-=4;
|
||||
|
@ -159,7 +160,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
_bytesNeeded=_state.getNeeds();
|
||||
_m=0;
|
||||
continue;
|
||||
|
||||
|
||||
case OPCODE:
|
||||
b=_buffer.get();
|
||||
available--;
|
||||
|
@ -167,7 +168,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
b^=_mask[_m++%4];
|
||||
_opcode=(byte)(b&0xf);
|
||||
_flags=(byte)(0xf&(b>>4));
|
||||
|
||||
|
||||
if (WebSocketConnectionD06.isControlFrame(_opcode)&&!WebSocketConnectionD06.isLastFrame(_flags))
|
||||
{
|
||||
_state=State.SKIP;
|
||||
|
@ -200,7 +201,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
default:
|
||||
_length=(0x7f&b);
|
||||
_bytesNeeded=(int)_length;
|
||||
_state=State.DATA;
|
||||
_state=State.DATA;
|
||||
}
|
||||
continue;
|
||||
|
||||
|
@ -247,7 +248,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
|
||||
case SKIP:
|
||||
int skip=Math.min(available,_bytesNeeded);
|
||||
_buffer.skip(skip);
|
||||
|
@ -255,7 +256,7 @@ public class WebSocketParserD06 implements WebSocketParser
|
|||
_bytesNeeded-=skip;
|
||||
if (_bytesNeeded==0)
|
||||
_state=State.START;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -31,9 +31,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class WebSocketParserD12 implements WebSocketParser
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketParserD12.class);
|
||||
|
||||
public enum State {
|
||||
|
||||
|
||||
public enum State {
|
||||
|
||||
START(0), OPCODE(1), LENGTH_7(1), LENGTH_16(2), LENGTH_63(8), MASK(4), PAYLOAD(0), DATA(0), SKIP(1);
|
||||
|
||||
int _needs;
|
||||
|
@ -47,7 +47,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
{
|
||||
return _needs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final WebSocketBuffers _buffers;
|
||||
private final EndPoint _endp;
|
||||
|
@ -70,8 +70,9 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
* @param buffers The buffers to use for parsing. Only the {@link Buffers#getBuffer()} is used.
|
||||
* This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
|
||||
* is mostly used.
|
||||
* @param endp
|
||||
* @param handler
|
||||
* @param endp the endpoint
|
||||
* @param handler the handler to notify when a parse event occurs
|
||||
* @param shouldBeMasked whether masking should be handled
|
||||
*/
|
||||
public WebSocketParserD12(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
|
||||
{
|
||||
|
@ -160,10 +161,10 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
events++;
|
||||
_bytesNeeded-=data.length();
|
||||
_handler.onFrame((byte)(_flags&(0xff^WebSocketConnectionD12.FLAG_FIN)), _opcode, data);
|
||||
|
||||
|
||||
_opcode=WebSocketConnectionD12.OP_CONTINUATION;
|
||||
}
|
||||
|
||||
|
||||
if (_buffer.space() == 0)
|
||||
throw new IllegalStateException("FULL: "+_state+" "+_bytesNeeded+">"+_buffer.capacity());
|
||||
}
|
||||
|
@ -185,7 +186,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
}
|
||||
|
||||
// if we are here, then we have sufficient bytes to process the current state.
|
||||
|
||||
|
||||
// Parse the buffer byte by byte (unless it is STATE_DATA)
|
||||
byte b;
|
||||
while (_state!=State.DATA && available>=(_state==State.SKIP?1:_bytesNeeded))
|
||||
|
@ -197,13 +198,13 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
_state=State.OPCODE;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
continue;
|
||||
|
||||
|
||||
case OPCODE:
|
||||
b=_buffer.get();
|
||||
available--;
|
||||
_opcode=(byte)(b&0xf);
|
||||
_flags=(byte)(0xf&(b>>4));
|
||||
|
||||
|
||||
if (WebSocketConnectionD12.isControlFrame(_opcode)&&!WebSocketConnectionD12.isLastFrame(_flags))
|
||||
{
|
||||
events++;
|
||||
|
@ -222,7 +223,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
available--;
|
||||
_masked=(b&0x80)!=0;
|
||||
b=(byte)(0x7f&b);
|
||||
|
||||
|
||||
switch(b)
|
||||
{
|
||||
case 0x7f:
|
||||
|
@ -235,7 +236,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
break;
|
||||
default:
|
||||
_length=(0x7f&b);
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
}
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
continue;
|
||||
|
@ -253,7 +254,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
_skip=true;
|
||||
}
|
||||
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
}
|
||||
continue;
|
||||
|
@ -272,7 +273,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
_skip=true;
|
||||
}
|
||||
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
}
|
||||
continue;
|
||||
|
@ -289,10 +290,10 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
_bytesNeeded=(int)_length;
|
||||
_state=_skip?State.SKIP:State.DATA;
|
||||
break;
|
||||
|
||||
|
||||
case DATA:
|
||||
break;
|
||||
|
||||
|
||||
case SKIP:
|
||||
int skip=Math.min(available,_bytesNeeded);
|
||||
_buffer.skip(skip);
|
||||
|
@ -300,7 +301,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
_bytesNeeded-=skip;
|
||||
if (_bytesNeeded==0)
|
||||
_state=State.START;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,12 +346,12 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
{
|
||||
if (_buffer==null)
|
||||
_buffer=_buffers.getBuffer();
|
||||
|
||||
|
||||
_buffer.put(buffer);
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void returnBuffer()
|
||||
{
|
||||
|
@ -360,7 +361,7 @@ public class WebSocketParserD12 implements WebSocketParser
|
|||
_buffer=null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
@ -31,9 +31,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class WebSocketParserD13 implements WebSocketParser
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketParserD13.class);
|
||||
|
||||
public enum State {
|
||||
|
||||
|
||||
public enum State {
|
||||
|
||||
START(0), OPCODE(1), LENGTH_7(1), LENGTH_16(2), LENGTH_63(8), MASK(4), PAYLOAD(0), DATA(0), SKIP(1);
|
||||
|
||||
int _needs;
|
||||
|
@ -47,7 +47,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
{
|
||||
return _needs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final WebSocketBuffers _buffers;
|
||||
private final EndPoint _endp;
|
||||
|
@ -70,8 +70,9 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
* @param buffers The buffers to use for parsing. Only the {@link Buffers#getBuffer()} is used.
|
||||
* This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
|
||||
* is mostly used.
|
||||
* @param endp
|
||||
* @param handler
|
||||
* @param endp the endpoint
|
||||
* @param handler the handler to notify when a parse event occurs
|
||||
* @param shouldBeMasked whether masking should be handled
|
||||
*/
|
||||
public WebSocketParserD13(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
|
||||
{
|
||||
|
@ -160,10 +161,10 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
events++;
|
||||
_bytesNeeded-=data.length();
|
||||
_handler.onFrame((byte)(_flags&(0xff^WebSocketConnectionD13.FLAG_FIN)), _opcode, data);
|
||||
|
||||
|
||||
_opcode=WebSocketConnectionD13.OP_CONTINUATION;
|
||||
}
|
||||
|
||||
|
||||
if (_buffer.space() == 0)
|
||||
throw new IllegalStateException("FULL: "+_state+" "+_bytesNeeded+">"+_buffer.capacity());
|
||||
}
|
||||
|
@ -185,7 +186,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
}
|
||||
|
||||
// if we are here, then we have sufficient bytes to process the current state.
|
||||
|
||||
|
||||
// Parse the buffer byte by byte (unless it is STATE_DATA)
|
||||
byte b;
|
||||
while (_state!=State.DATA && available>=(_state==State.SKIP?1:_bytesNeeded))
|
||||
|
@ -197,13 +198,13 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_state=State.OPCODE;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
continue;
|
||||
|
||||
|
||||
case OPCODE:
|
||||
b=_buffer.get();
|
||||
available--;
|
||||
_opcode=(byte)(b&0xf);
|
||||
_flags=(byte)(0xf&(b>>4));
|
||||
|
||||
|
||||
if (WebSocketConnectionD13.isControlFrame(_opcode)&&!WebSocketConnectionD13.isLastFrame(_flags))
|
||||
{
|
||||
events++;
|
||||
|
@ -222,7 +223,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
available--;
|
||||
_masked=(b&0x80)!=0;
|
||||
b=(byte)(0x7f&b);
|
||||
|
||||
|
||||
switch(b)
|
||||
{
|
||||
case 0x7f:
|
||||
|
@ -235,7 +236,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
break;
|
||||
default:
|
||||
_length=(0x7f&b);
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
}
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
continue;
|
||||
|
@ -253,7 +254,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_skip=true;
|
||||
}
|
||||
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
}
|
||||
continue;
|
||||
|
@ -272,7 +273,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_skip=true;
|
||||
}
|
||||
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_state=_masked?State.MASK:State.PAYLOAD;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
}
|
||||
continue;
|
||||
|
@ -289,10 +290,10 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_bytesNeeded=(int)_length;
|
||||
_state=_skip?State.SKIP:State.DATA;
|
||||
break;
|
||||
|
||||
|
||||
case DATA:
|
||||
break;
|
||||
|
||||
|
||||
case SKIP:
|
||||
int skip=Math.min(available,_bytesNeeded);
|
||||
_buffer.skip(skip);
|
||||
|
@ -300,7 +301,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_bytesNeeded-=skip;
|
||||
if (_bytesNeeded==0)
|
||||
_state=State.START;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,12 +346,12 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
{
|
||||
if (_buffer==null)
|
||||
_buffer=_buffers.getBuffer();
|
||||
|
||||
|
||||
_buffer.put(buffer);
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void returnBuffer()
|
||||
{
|
||||
|
@ -360,7 +361,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_buffer=null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
|
|
|
@ -80,7 +80,7 @@ public class WebSocketClientTest
|
|||
{
|
||||
}
|
||||
};
|
||||
Future<WebSocket.Connection> future = client.open(new URI("ws://127.0.0.1:" + _serverPort + "/"), websocket);
|
||||
client.open(new URI("ws://127.0.0.1:" + _serverPort + "/"), websocket);
|
||||
|
||||
Socket socket = _server.accept();
|
||||
accept(socket);
|
||||
|
|
|
@ -909,6 +909,98 @@ public class WebSocketMessageD13Test
|
|||
lookFor("Message size > 15",input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseCode() throws Exception
|
||||
{
|
||||
Socket socket = new Socket("localhost", __connector.getLocalPort());
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(
|
||||
("GET /chat HTTP/1.1\r\n"+
|
||||
"Host: server.example.com\r\n"+
|
||||
"Upgrade: websocket\r\n"+
|
||||
"Connection: Upgrade\r\n"+
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: chat\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
socket.setSoTimeout(100000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
skipTo("\r\n\r\n",input);
|
||||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
__serverWebSocket.getConnection().setMaxBinaryMessageSize(15);
|
||||
|
||||
output.write(0x88);
|
||||
output.write(0x82);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x81);
|
||||
output.write(0xFF);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(2,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(0x81FF,code);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotUTF8() throws Exception
|
||||
{
|
||||
Socket socket = new Socket("localhost", __connector.getLocalPort());
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(
|
||||
("GET /chat HTTP/1.1\r\n"+
|
||||
"Host: server.example.com\r\n"+
|
||||
"Upgrade: websocket\r\n"+
|
||||
"Connection: Upgrade\r\n"+
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: chat\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
socket.setSoTimeout(100000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
skipTo("\r\n\r\n",input);
|
||||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
__serverWebSocket.getConnection().setMaxBinaryMessageSize(15);
|
||||
|
||||
output.write(0x81);
|
||||
output.write(0x82);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0xc3);
|
||||
output.write(0x28);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(15,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_NOT_UTF8,code);
|
||||
lookFor("Invalid UTF-8",input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxBinarySize2() throws Exception
|
||||
|
|
|
@ -130,13 +130,6 @@ public class WebSocketParserD00Test
|
|||
}
|
||||
|
||||
|
||||
// TODO test:
|
||||
// blocking,
|
||||
// async
|
||||
// full
|
||||
// EOF
|
||||
// errors
|
||||
|
||||
private class Handler implements WebSocketParser.FrameHandler
|
||||
{
|
||||
public List<String> _data = new ArrayList<String>();
|
||||
|
|
|
@ -242,6 +242,7 @@ public abstract class ContinuationBase extends TestCase
|
|||
try
|
||||
{
|
||||
Socket socket = new Socket("localhost",port);
|
||||
socket.setSoTimeout(10000);
|
||||
socket.getOutputStream().write(request.getBytes("UTF-8"));
|
||||
|
||||
response = toString(socket.getInputStream());
|
||||
|
|
|
@ -36,7 +36,7 @@ public class HashTestServer extends AbstractTestServer
|
|||
}
|
||||
|
||||
|
||||
public SessionIdManager newSessionIdManager()
|
||||
public SessionIdManager newSessionIdManager(String config)
|
||||
{
|
||||
return new HashSessionIdManager();
|
||||
}
|
||||
|
|
|
@ -22,22 +22,29 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
public class JdbcTestServer extends AbstractTestServer
|
||||
{
|
||||
public static final String DRIVER_CLASS = "org.apache.derby.jdbc.EmbeddedDriver";
|
||||
public static final String CONNECTION_URL = "jdbc:derby:sessions;create=true";
|
||||
public static final String DEFAULT_CONNECTION_URL = "jdbc:derby:sessions;create=true";
|
||||
public static final int SAVE_INTERVAL = 1;
|
||||
|
||||
|
||||
static
|
||||
{
|
||||
System.setProperty("derby.system.home", MavenTestingUtils.getTargetFile("test-derby").getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
public JdbcTestServer(int port)
|
||||
{
|
||||
super(port);
|
||||
}
|
||||
|
||||
|
||||
public JdbcTestServer(int port, int maxInactivePeriod, int scavengePeriod, String connectionUrl)
|
||||
{
|
||||
super(port, maxInactivePeriod, scavengePeriod, connectionUrl);
|
||||
}
|
||||
|
||||
public JdbcTestServer(int port, int maxInactivePeriod, int scavengePeriod)
|
||||
{
|
||||
super(port, maxInactivePeriod, scavengePeriod);
|
||||
super(port, maxInactivePeriod, scavengePeriod, DEFAULT_CONNECTION_URL);
|
||||
}
|
||||
|
||||
public JdbcTestServer (int port, boolean optimize)
|
||||
|
@ -60,14 +67,14 @@ public class JdbcTestServer extends AbstractTestServer
|
|||
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionIdManager()
|
||||
*/
|
||||
@Override
|
||||
public SessionIdManager newSessionIdManager()
|
||||
public SessionIdManager newSessionIdManager(String config)
|
||||
{
|
||||
synchronized(JdbcTestServer.class)
|
||||
{
|
||||
JDBCSessionIdManager idManager = new JDBCSessionIdManager(_server);
|
||||
idManager.setScavengeInterval(_scavengePeriod);
|
||||
idManager.setWorkerName("w"+(__workers++));
|
||||
idManager.setDriverInfo(DRIVER_CLASS, CONNECTION_URL);
|
||||
idManager.setDriverInfo(DRIVER_CLASS, (config==null?DEFAULT_CONNECTION_URL:config));
|
||||
return idManager;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,16 @@ package org.eclipse.jetty.server.session;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionActivationListener;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
|
@ -30,6 +34,8 @@ public abstract class AbstractRemoveSessionTest
|
|||
AbstractTestServer server = createServer(0, 1, scavengePeriod);
|
||||
ServletContextHandler context = server.addContext(contextPath);
|
||||
context.addServlet(TestServlet.class, servletMapping);
|
||||
TestEventListener testListener = new TestEventListener();
|
||||
context.getSessionHandler().addEventListener(testListener);
|
||||
server.start();
|
||||
int port = server.getPort();
|
||||
try
|
||||
|
@ -49,6 +55,8 @@ public abstract class AbstractRemoveSessionTest
|
|||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
//ensure sessionCreated listener is called
|
||||
assertTrue (testListener.isCreated());
|
||||
|
||||
//now delete the session
|
||||
exchange = new ContentExchange(true);
|
||||
|
@ -58,6 +66,8 @@ public abstract class AbstractRemoveSessionTest
|
|||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
//ensure sessionDestroyed listener is called
|
||||
assertTrue(testListener.isDestroyed());
|
||||
|
||||
|
||||
// The session is not there anymore, but we present an old cookie
|
||||
|
@ -106,4 +116,32 @@ public abstract class AbstractRemoveSessionTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class TestEventListener implements HttpSessionListener
|
||||
{
|
||||
boolean wasCreated;
|
||||
boolean wasDestroyed;
|
||||
|
||||
public void sessionCreated(HttpSessionEvent se)
|
||||
{
|
||||
wasCreated = true;
|
||||
}
|
||||
|
||||
public void sessionDestroyed(HttpSessionEvent se)
|
||||
{
|
||||
wasDestroyed = true;
|
||||
}
|
||||
|
||||
public boolean isDestroyed()
|
||||
{
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCreated()
|
||||
{
|
||||
return wasCreated;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,22 +34,31 @@ public abstract class AbstractTestServer
|
|||
protected final ContextHandlerCollection _contexts;
|
||||
protected SessionIdManager _sessionIdManager;
|
||||
|
||||
|
||||
|
||||
public AbstractTestServer(int port)
|
||||
{
|
||||
this(port, 30, 10);
|
||||
}
|
||||
|
||||
public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod)
|
||||
{
|
||||
this (port, maxInactivePeriod, scavengePeriod, null);
|
||||
}
|
||||
|
||||
public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod, String sessionIdMgrConfig)
|
||||
{
|
||||
_server = new Server(port);
|
||||
_maxInactivePeriod = maxInactivePeriod;
|
||||
_scavengePeriod = scavengePeriod;
|
||||
_contexts = new ContextHandlerCollection();
|
||||
_sessionIdManager = newSessionIdManager();
|
||||
_sessionIdManager = newSessionIdManager(sessionIdMgrConfig);
|
||||
_server.setSessionIdManager(_sessionIdManager);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public abstract SessionIdManager newSessionIdManager();
|
||||
public abstract SessionIdManager newSessionIdManager(String config);
|
||||
public abstract SessionManager newSessionManager();
|
||||
public abstract SessionHandler newSessionHandler(SessionManager sessionManager);
|
||||
|
||||
|
|
Loading…
Reference in New Issue