Merge over from jetty 7 master

This commit is contained in:
Jesse McConnell 2011-09-07 16:08:35 -05:00
commit 7c7fc30b90
54 changed files with 905 additions and 685 deletions

View File

@ -1,9 +1,15 @@
jetty-8.0.1-SNAPSHOT
jetty-8.0.0.v20110901 - 01 September 2011
+ 352565 cookie httponly flag ignored
+ 353073 better warnings
+ 353285 ServletSecurity annotation ignored
+ 356421 Upgraded websocket to draft 13 support
jetty-7.5.0.v20110901 - 01 September 2011
+ 356421 Upgraded websocket to draft 13 support
+ 353073 better warnings
jetty-7.5.0.RC2 - 30 August 2011
+ 293739 Hide stacks in named log testing. Various other minor log cleanups in
output.
@ -73,6 +79,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 - 25 July 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

View File

@ -336,7 +336,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;

View File

@ -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;

View File

@ -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}")));
}

View File

@ -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();

View File

@ -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)
{

View File

@ -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();

View File

@ -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);
}
}

View File

@ -124,6 +124,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>

View File

@ -52,7 +52,7 @@ public class MongoTestServer extends AbstractTestServer
_saveAllAttributes = saveAllAttributes;
}
public SessionIdManager newSessionIdManager()
public SessionIdManager newSessionIdManager(String config)
{
if ( _idManager != null )
{

View File

@ -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();

View File

@ -115,6 +115,7 @@ public class DigestAuthenticator extends LoginAuthenticator
break;
case ',':
name = null;
break;
case ' ':
break;

View File

@ -704,7 +704,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
listener.sessionDestroyed(event);
}
}
}

View File

@ -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"+

View File

@ -148,8 +148,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);
}
/* ------------------------------------------------------------ */

View File

@ -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");
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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)
{

View 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

View File

@ -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());
}

View File

@ -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());
}

View File

@ -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,7 +149,7 @@ 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()
@ -162,15 +163,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
@ -182,9 +183,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.
@ -196,7 +197,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super(parent,contextPath,SESSIONS|SECURITY);
_scontext=new Context();
setWar(webApp);
setErrorHandler(new ErrorPageErrorHandler());
setErrorHandler(new ErrorPageErrorHandler());
}
/* ------------------------------------------------------------ */
@ -214,7 +215,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_scontext = new Context();
setErrorHandler(errorHandler != null ? errorHandler : new ErrorPageErrorHandler());
}
/* ------------------------------------------------------------ */
/**
* @param servletContextName The servletContextName to set.
@ -227,7 +228,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
@ -237,7 +238,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return _unavailableException;
}
/* ------------------------------------------------------------ */
/** Set Resource Alias.
* Resource aliases map resource uri's within a context.
@ -260,13 +261,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)
{
@ -291,16 +292,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
@ -318,7 +319,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)
@ -334,11 +335,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return resource;
}
/* ------------------------------------------------------------ */
/** Is the context Automatically configured.
*
*
* @return true if configuration discovery.
*/
public boolean isConfigurationDiscovered()
@ -360,7 +361,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
_configurationDiscovered = discovered;
}
/* ------------------------------------------------------------ */
/** Pre configure the web application.
* <p>
@ -371,7 +372,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
@ -383,7 +384,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
// Setup system classes
loadSystemClasses();
// Setup server classes
loadServerClasses();
@ -407,8 +408,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]);
@ -426,10 +427,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++)
{
@ -437,7 +438,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_configurations[i].postConfigure(this);
}
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.thread.AbstractLifeCycle#doStart()
@ -465,7 +466,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
throw e;
}
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.thread.AbstractLifeCycle#doStop()
@ -479,11 +480,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
{
@ -494,19 +495,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)
@ -534,7 +535,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());
}
}
@ -547,7 +548,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
return _configurationClasses;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the configurations.
@ -556,7 +557,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
@ -566,7 +567,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
@ -579,7 +580,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
@ -589,7 +590,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
return Collections.unmodifiableList(_overrideDescriptors);
}
/* ------------------------------------------------------------ */
/**
* @return Returns the permissions.
@ -608,7 +609,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
if (_serverClasses == null)
loadServerClasses();
return _serverClasses.getPatterns();
}
@ -616,10 +617,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
if (_serverClasses == null)
loadServerClasses();
_serverClasses.addPattern(classname);
}
/* ------------------------------------------------------------ */
/**
* @see #setSystemClasses(String[])
@ -629,25 +630,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);
}
@ -656,16 +657,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();
@ -675,17 +676,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();
@ -695,11 +696,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)
@ -721,10 +722,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.
@ -763,35 +764,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
@ -810,17 +811,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
@ -842,7 +843,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_configurationClassesSet = true;
_configurations=null;
}
/* ------------------------------------------------------------ */
/**
* @param configurations The configurations to set.
@ -876,7 +877,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
@ -887,7 +888,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
@ -915,7 +916,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
_descriptor=descriptor;
}
/* ------------------------------------------------------------ */
/**
* @param distributable The distributable to set.
@ -931,13 +932,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)
@ -946,7 +947,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
if (_sessionHandler!=null)
_sessionHandler.addEventListener(listener);
}
}
}
@ -957,11 +958,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
@ -970,7 +971,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
_extractWAR = extractWAR;
}
/* ------------------------------------------------------------ */
/**
* @param copy True if the webdir is copied (to allow hot replacement of jars)
@ -1006,10 +1007,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
@ -1040,7 +1041,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
_serverClasses = new ClasspathPattern(serverClasses);
}
/* ------------------------------------------------------------ */
/**
* Set the system classes patterns.
@ -1060,7 +1061,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
_systemClasses = new ClasspathPattern(systemClasses);
}
/* ------------------------------------------------------------ */
/** Set temporary directory for context.
@ -1086,7 +1087,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)
@ -1099,13 +1100,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
@ -1153,14 +1154,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)
@ -1171,46 +1172,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
{
@ -1220,7 +1221,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())
{
@ -1231,7 +1232,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return resources[i].getURL();
}
}
return resource.getURL();
}
@ -1240,7 +1241,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 )
@ -1250,7 +1251,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return servletContext;
}
}
return null;
}
else

View File

@ -1,77 +1,98 @@
<?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>8.0.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>
<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>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
<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>
<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>

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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");

View File

@ -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");

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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()

View File

@ -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()

View File

@ -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);

View File

@ -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

View File

@ -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>();

View File

@ -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());

View File

@ -173,7 +173,7 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
<!--scope>provided</scope-->
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>

View File

@ -36,7 +36,7 @@ public class HashTestServer extends AbstractTestServer
}
public SessionIdManager newSessionIdManager()
public SessionIdManager newSessionIdManager(String config)
{
return new HashSessionIdManager();
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);