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

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

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

@ -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;
@ -99,8 +98,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"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
@ -112,9 +112,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"-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
} ;

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

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,10 +5,11 @@ 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)
@ -18,6 +19,9 @@ public class RandomMaskGen implements MaskGen
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

@ -31,12 +31,11 @@ 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()

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)
{
@ -382,19 +382,20 @@ 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

@ -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;
@ -65,7 +65,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
_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)
{
@ -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,11 +369,15 @@ 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");
@ -449,12 +451,11 @@ 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;
}
@ -488,7 +489,6 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
public void close(int code,String message)
{
close(code,message);
}
}

View File

@ -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;
@ -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;
@ -116,7 +115,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
{
super(endpoint,timestamp);
// TODO - can we use the endpoint idle mechanism?
if (endpoint instanceof AsyncEndPoint)
((AsyncEndPoint)endpoint).cancelIdle();
@ -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;
@ -734,10 +731,6 @@ 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");

View File

@ -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;
@ -164,7 +163,6 @@ public class WebSocketConnectionD12 extends AbstractConnection implements WebSoc
_protocol=protocol;
// TODO should these be AsyncEndPoint checks/calls?
if (_endp instanceof SelectChannelEndPoint)
{
final SelectChannelEndPoint scep=(SelectChannelEndPoint)_endp;
@ -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);
@ -833,13 +830,9 @@ 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)

View File

@ -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;
@ -84,7 +84,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
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;
@ -114,8 +113,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
}
}
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
@ -148,6 +145,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
_generator = new WebSocketGeneratorD13(buffers, _endp,maskgen);
_extensions=extensions;
WebSocketParser.FrameHandler frameHandler = new WSFrameHandler();
if (_extensions!=null)
{
int e=0;
@ -155,16 +153,16 @@ 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);
WebSocketParser.FrameHandler inbound = (_extensions == null || _extensions.size() == 0) ? frameHandler : extensions.get(0);
_parser = new WebSocketParserD13(buffers, endpoint,_inbound,maskgen==null);
_parser = new WebSocketParserD13(buffers, endpoint, inbound,maskgen==null);
_protocol=protocol;
@ -302,14 +300,14 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
{
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,14 +316,14 @@ 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
closeOut(code,message);
@ -343,13 +341,15 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
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;
@ -358,16 +358,14 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
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)
@ -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);
}
@ -780,6 +782,12 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
}
}
}
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;
@ -837,10 +845,6 @@ 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");

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

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

@ -14,8 +14,6 @@
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;
@ -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),
@ -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

@ -66,7 +66,6 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
_buffer=mask?_buffers.getBuffer():_buffers.getDirectBuffer();
boolean last=WebSocketConnectionD12.isLastFrame(flags);
byte orig=opcode;
int space=mask?14:10;
@ -100,10 +99,10 @@ public class WebSocketGeneratorD12 implements WebSocketGenerator
_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),

View File

@ -66,7 +66,6 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
_buffer=mask?_buffers.getBuffer():_buffers.getDirectBuffer();
boolean last=WebSocketConnectionD13.isLastFrame(flags);
byte orig=opcode;
int space=mask?14:10;
@ -100,10 +99,10 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
_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),

View File

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

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

View File

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

View File

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

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