binary tests akin to previous text frame tests

This commit is contained in:
Jesse McConnell 2012-06-26 13:48:25 -05:00
parent aba59b6dc0
commit 9a9d24ecff
4 changed files with 678 additions and 125 deletions

View File

@ -16,6 +16,12 @@ public class BinaryFrame extends DataFrame
super(OpCode.BINARY);
}
public BinaryFrame( byte[] payload )
{
this();
setPayload(payload);
}
@Override
public String toString()
{

View File

@ -10,17 +10,15 @@ import org.eclipse.jetty.websocket.ByteBufferAssert;
import org.eclipse.jetty.websocket.Debug;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BinaryFrame;
import org.eclipse.jetty.websocket.frames.TextFrame;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.parser.TextPayloadParser;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
public class ABCase1
public class ABCase1_1
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
@ -421,8 +419,8 @@ public class ABCase1
@Test
public void testParse65535ByteTextCase1_1_6()
{
Debug.enableDebugLogging(Parser.class);
Debug.enableDebugLogging(TextPayloadParser.class);
//Debug.enableDebugLogging(Parser.class);
//Debug.enableDebugLogging(TextPayloadParser.class);
int length = 65535;

View File

@ -0,0 +1,544 @@
package org.eclipse.jetty.websocket.ab;
import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.StandardByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.ByteBufferAssert;
import org.eclipse.jetty.websocket.Debug;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BinaryFrame;
import org.eclipse.jetty.websocket.frames.TextFrame;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.parser.TextPayloadParser;
import org.junit.Assert;
import org.junit.Test;
public class ABCase1_2
{
StandardByteBufferPool bufferPool = new StandardByteBufferPool();
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
@Test
public void testGenerateEmptyBinaryCase1_2_1()
{
BinaryFrame binaryFrame = new BinaryFrame(new byte[]{});
binaryFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(binaryFrame);
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x82, (byte)0x00 });
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParseEmptyBinaryCase1_2_1()
{
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x82, (byte)0x00 });
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0));
ByteBufferAssert.assertSize("BinaryFrame.payload",0,pActual.getPayload());
}
@Test
public void testGenerate125ByteBinaryCase1_2_2()
{
int length = 125;
ByteBuffer bb = ByteBuffer.allocate(length);
for ( int i = 0 ; i < length ; ++i)
{
bb.put("*".getBytes());
}
bb.flip();
BinaryFrame binaryFrame = new BinaryFrame( BufferUtil.toArray(bb) );
binaryFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(binaryFrame);
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= length & 0x7F;
expected.put(b);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse125ByteBinaryCase1_2_2()
{
int length = 125;
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= length & 0x7F;
expected.put(b);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
}
@Test
public void testGenerate126ByteBinaryCase1_2_3()
{
int length = 126;
ByteBuffer bb = ByteBuffer.allocate(length);
for ( int i = 0 ; i < length ; ++i)
{
bb.put("*".getBytes());
}
bb.flip();
BinaryFrame binaryFrame = new BinaryFrame(BufferUtil.toArray(bb));
binaryFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(binaryFrame);
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= length & 0x7E;
expected.put(b);
//expected.put((byte)((length>>8) & 0xFF));
//expected.put((byte)(length & 0xFF));
expected.putShort((short)length);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse126ByteBinaryCase1_2_3()
{
int length = 126;
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= length & 0x7E;
expected.put(b);
expected.putShort((short)length);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
}
@Test
public void testGenerate127ByteBinaryCase1_2_4()
{
int length = 127;
ByteBuffer bb = ByteBuffer.allocate(length);
for ( int i = 0 ; i < length ; ++i)
{
bb.put("*".getBytes());
}
bb.flip();
BinaryFrame binaryFrame = new BinaryFrame(BufferUtil.toArray(bb));
binaryFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(binaryFrame);
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= length & 0x7E;
expected.put(b);
//expected.put((byte)((length>>8) & 0xFF));
//expected.put((byte)(length & 0xFF));
expected.putShort((short)length);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse127ByteBinaryCase1_2_4()
{
int length = 127;
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= length & 0x7E;
expected.put(b);
expected.putShort((short)length);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
}
@Test
public void testGenerate128ByteBinaryCase1_2_5()
{
int length = 128;
ByteBuffer bb = ByteBuffer.allocate(length);
for ( int i = 0 ; i < length ; ++i)
{
bb.put("*".getBytes());
}
bb.flip();
BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb));
textFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(textFrame);
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= 0x7E;
expected.put(b);
expected.put((byte)(length>>8));
expected.put((byte)(length & 0xFF));
//expected.putShort((short)length);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse128ByteBinaryCase1_2_5()
{
int length = 128;
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= 0x7E;
expected.put(b);
expected.putShort((short)length);
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
}
@Test
public void testGenerate65535ByteBinaryCase1_2_6()
{
int length = 65535;
ByteBuffer bb = ByteBuffer.allocate(length);
for ( int i = 0 ; i < length ; ++i)
{
bb.put("*".getBytes());
}
bb.flip();
BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb));
textFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(textFrame);
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= 0x7E;
expected.put(b);
expected.put(new byte[]{ (byte)0xff, (byte)0xff});
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse65535ByteBinaryCase1_2_6()
{
int length = 65535;
ByteBuffer expected = ByteBuffer.allocate(length + 5);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= 0x7E;
expected.put(b);
expected.put(new byte[]{ (byte)0xff, (byte)0xff});
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
expected.flip();
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
policy.setMaxTextMessageSize(length);
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
}
@Test
public void testGenerate65536ByteBinaryCase1_2_7()
{
int length = 65536;
ByteBuffer bb = ByteBuffer.allocate(length);
for ( int i = 0 ; i < length ; ++i)
{
bb.put("*".getBytes());
}
bb.flip();
BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb));
textFrame.setFin(true);
Generator generator = new Generator(bufferPool,policy);
ByteBuffer actual = generator.generate(textFrame);
ByteBuffer expected = ByteBuffer.allocate(length + 11);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= 0x7F;
expected.put(b);
expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse65536ByteBinaryCase1_2_7()
{
int length = 65536;
ByteBuffer expected = ByteBuffer.allocate(length + 11);
expected.put(new byte[]
{ (byte)0x82 });
byte b = 0x00; // no masking
b |= 0x7F;
expected.put(b);
expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});
for ( int i = 0 ; i < length ; ++i )
{
expected.put("*".getBytes());
}
expected.flip();
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
policy.setMaxTextMessageSize(length);
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(BinaryFrame.class,1);
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
}
}

View File

@ -15,101 +15,87 @@ package org.eclipse.jetty.websocket.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.StandardByteBufferPool;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.api.ExtensionConfig;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.extensions.Extension;
import org.eclipse.jetty.websocket.extensions.deflate.DeflateFrameExtension;
import org.eclipse.jetty.websocket.extensions.fragment.FragmentExtension;
import org.eclipse.jetty.websocket.extensions.identity.IdentityExtension;
import org.eclipse.jetty.websocket.server.handshake.HandshakeHixie76;
import org.eclipse.jetty.websocket.server.handshake.HandshakeRFC6455;
/**
* Factory to create WebSocket connections
*/
public class WebSocketServerFactory extends AbstractLifeCycle
{
public interface Acceptor
{
/* ------------------------------------------------------------ */
/**
* <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);
/* ------------------------------------------------------------ */
/**
* <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);
}
private static final Logger LOG = Log.getLogger(WebSocketServerFactory.class);
private static final int RESPONSE_BUFFER_SIZE = 8192;
private final Queue<AsyncWebSocketConnection> connections = new ConcurrentLinkedQueue<AsyncWebSocketConnection>();
private final Queue<WebSocketServletConnection> connections = new ConcurrentLinkedQueue<WebSocketServletConnection>();
// TODO: replace with ExtensionRegistry in websocket-core
private final Map<String, Class<? extends Extension>> extensionClasses = new HashMap<>();
private final Map<String,Class<? extends Extension>> _extensionClasses = new HashMap<String, Class<? extends Extension>>();
{
extensionClasses.put("identity",IdentityExtension.class);
extensionClasses.put("fragment",FragmentExtension.class);
extensionClasses.put("x-deflate-frame",DeflateFrameExtension.class);
_extensionClasses.put("identity",IdentityExtension.class);
_extensionClasses.put("fragment",FragmentExtension.class);
_extensionClasses.put("x-deflate-frame",DeflateFrameExtension.class);
}
private final Map<Integer, WebSocketServer.Handshake> handshakes = new HashMap<>();
{
handshakes.put(HandshakeRFC6455.VERSION,new HandshakeRFC6455());
handshakes.put(HandshakeHixie76.VERSION,new HandshakeHixie76());
}
private final WebSocketServer.Acceptor acceptor;
private final ByteBufferPool bufferPool;
private final String supportedVersions;
private final Acceptor _acceptor;
private WebSocketPolicy policy;
public WebSocketServerFactory(WebSocketServer.Acceptor acceptor, WebSocketPolicy policy)
public WebSocketServerFactory(Acceptor acceptor, WebSocketPolicy policy)
{
this.acceptor = acceptor;
this._acceptor = acceptor;
this.policy = policy;
this.bufferPool = new StandardByteBufferPool(RESPONSE_BUFFER_SIZE);
// Create supportedVersions
List<Integer> versions = new ArrayList<>();
for (int v : handshakes.keySet())
{
versions.add(v);
}
Collections.sort(versions,Collections.reverseOrder()); // newest first
StringBuilder rv = new StringBuilder();
for (int v : versions)
{
if (rv.length() > 0)
{
rv.append(", ");
}
rv.append(v);
}
supportedVersions = rv.toString();
}
public boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException
public boolean ˇ(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
if ("websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
{
String origin = request.getHeader("Origin");
if (origin == null)
if (origin==null)
{
origin = request.getHeader("Sec-WebSocket-Origin");
}
if (!acceptor.checkOrigin(request,origin))
if (!_acceptor.checkOrigin(request,origin))
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return false;
@ -118,14 +104,15 @@ public class WebSocketServerFactory extends AbstractLifeCycle
// Try each requested protocol
WebSocket websocket = null;
@SuppressWarnings("unchecked")
Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
String protocol = null;
while ((protocol == null) && (protocols != null) && protocols.hasMoreElements())
String protocol=null;
while ((protocol==null) && (protocols!=null) && protocols.hasMoreElements())
{
String candidate = protocols.nextElement();
for (String p : parseProtocols(candidate))
{
websocket = acceptor.doWebSocketConnect(request,p);
websocket = _acceptor.doWebSocketConnect(request, p);
if (websocket != null)
{
protocol = p;
@ -138,9 +125,9 @@ public class WebSocketServerFactory extends AbstractLifeCycle
if (websocket == null)
{
// Try with no protocol
websocket = acceptor.doWebSocketConnect(request,null);
websocket = _acceptor.doWebSocketConnect(request, null);
if (websocket == null)
if (websocket==null)
{
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return false;
@ -148,23 +135,23 @@ public class WebSocketServerFactory extends AbstractLifeCycle
}
// Send the upgrade
upgrade(request,response,websocket,protocol);
upgrade(request, response, websocket, protocol);
return true;
}
return false;
}
protected boolean addConnection(AsyncWebSocketConnection connection)
protected boolean addConnection(WebSocketServletConnection connection)
{
return isRunning() && connections.add(connection);
}
protected void closeConnections()
{
for (AsyncWebSocketConnection connection : connections)
for (WebSocketServletConnection connection : connections)
{
connection.getEndPoint().close();
// TODO connection.shutdown();
}
}
@ -177,9 +164,9 @@ public class WebSocketServerFactory extends AbstractLifeCycle
/**
* @return A modifiable map of extension name to extension class
*/
public Map<String, Class<? extends Extension>> getExtensionClassesMap()
public Map<String,Class<? extends Extension>> getExtensionClassesMap()
{
return extensionClasses;
return _extensionClasses;
}
/**
@ -192,23 +179,35 @@ public class WebSocketServerFactory extends AbstractLifeCycle
return policy;
}
public List<Extension> initExtensions(List<ExtensionConfig> requested)
public List<Extension> initExtensions(List<String> requested,int maxDataOpcodes,int maxControlOpcodes,int maxReservedBits)
{
List<Extension> extensions = new ArrayList<Extension>();
for (ExtensionConfig cfg : requested)
for (String rExt : requested)
{
Extension extension = newExtension(cfg.getName());
QuotedStringTokenizer tok = new QuotedStringTokenizer(rExt,";");
String extName=tok.nextToken().trim();
Map<String,String> parameters = new HashMap<String,String>();
while (tok.hasMoreTokens())
{
QuotedStringTokenizer nv = new QuotedStringTokenizer(tok.nextToken().trim(),"=");
String name=nv.nextToken().trim();
String value=nv.hasMoreTokens()?nv.nextToken().trim():null;
parameters.put(name,value);
}
if (extension == null)
Extension extension = newExtension(extName);
if (extension==null)
{
continue;
}
extension.setConfig(cfg);
LOG.debug("added {}",extension);
if (extension.init(parameters))
{
LOG.debug("add {} {}",extName,parameters);
extensions.add(extension);
}
}
LOG.debug("extensions={}",extensions);
return extensions;
}
@ -217,8 +216,8 @@ public class WebSocketServerFactory extends AbstractLifeCycle
{
try
{
Class<? extends Extension> extClass = extensionClasses.get(name);
if (extClass != null)
Class<? extends Extension> extClass = _extensionClasses.get(name);
if (extClass!=null)
{
return extClass.newInstance();
}
@ -235,18 +234,16 @@ public class WebSocketServerFactory extends AbstractLifeCycle
{
if (protocol == null)
{
return new String[]
{ null };
return new String[]{null};
}
protocol = protocol.trim();
if ((protocol == null) || (protocol.length() == 0))
{
return new String[]
{ null };
return new String[]{null};
}
String[] passed = protocol.split("\\s*,\\s*");
String[] protocols = new String[passed.length + 1];
System.arraycopy(passed,0,protocols,0,passed.length);
System.arraycopy(passed, 0, protocols, 0, passed.length);
return protocols;
}
@ -257,79 +254,87 @@ public class WebSocketServerFactory extends AbstractLifeCycle
/**
* Upgrade the request/response to a WebSocket Connection.
* <p>
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
* connection.
* <p>This method will not normally return, but will instead throw a
* UpgradeConnectionException, to exit HTTP handling and initiate
* WebSocket handling of the connection.
*
* @param request
* The request to upgrade
* @param response
* The response to upgrade
* @param websocket
* The websocket handler implementation to use
* @param acceptedSubProtocol
* The accepted websocket sub protocol
* @throws IOException
* in case of I/O errors
* @param request The request to upgrade
* @param response The response to upgrade
* @param websocket The websocket handler implementation to use
* @param protocol The websocket protocol
* @throws IOException in case of I/O errors
*/
public void upgrade(HttpServletRequest request, HttpServletResponse response, WebSocket websocket, String acceptedSubProtocol) throws IOException
public void upgrade(HttpServletRequest request, HttpServletResponse response, WebSocket websocket, String protocol)
throws IOException
{
if (!"websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
{
throw new IllegalStateException("Not a 'WebSocket: Ugprade' request");
throw new IllegalStateException("!Upgrade:websocket");
}
if (!"HTTP/1.1".equals(request.getProtocol()))
{
throw new IllegalStateException("Not a 'HTTP/1.1' request");
throw new IllegalStateException("!HTTP/1.1");
}
int version = request.getIntHeader("Sec-WebSocket-Version");
if (version < 0)
{
int draft = request.getIntHeader("Sec-WebSocket-Version");
if (draft < 0) {
// Old pre-RFC version specifications (header not present in RFC-6455)
version = request.getIntHeader("Sec-WebSocket-Draft");
draft = request.getIntHeader("Sec-WebSocket-Draft");
}
HttpConnection http = HttpConnection.getCurrentConnection();
AsyncEndPoint endp = http.getEndPoint();
List<ExtensionConfig> extensionsRequested = new ArrayList<>();
List<String> extensions_requested = new ArrayList<String>();
@SuppressWarnings("unchecked")
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
while (e.hasMoreElements())
{
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),",");
while (tok.hasMoreTokens())
{
extensionsRequested.add(ExtensionConfig.parse(tok.nextToken()));
extensions_requested.add(tok.nextToken());
}
}
WebSocketServer.Handshake handshaker = handshakes.get(version);
if (handshaker == null)
final WebSocketServletConnection connection;
switch (draft)
{
LOG.warn("Unsupported Websocket version: " + version);
case org.eclipse.jetty.websocket.api.WebSocket.VERSION: // RFC 6455 Version
{
// List<Extension> extensions = initExtensions(extensions_requested,
// 8 - WebSocketConnectionRFC6455.OP_EXT_DATA,
// 16 - WebSocketConnectionRFC6455.OP_EXT_CTRL,
// 3);
// connection = new WebSocketServletConnectionRFC6455(this, websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol, extensions, draft);
break;
}
default:
{
LOG.warn("Unsupported Websocket version: " + draft);
// Per RFC 6455 - 4.4 - Supporting Multiple Versions of WebSocket Protocol
// Using the examples as outlined
response.setHeader("Sec-WebSocket-Version",supportedVersions);
response.sendError(HttpStatus.BAD_REQUEST_400,"Unsupported websocket version specification");
response.setHeader("Sec-WebSocket-Version", "" + org.eclipse.jetty.websocket.api.WebSocket.VERSION /*+ ", 0"*/);
response.setStatus(HttpStatus.BAD_REQUEST_400);
return;
}
}
// Create connection
HttpConnection http = HttpConnection.getCurrentConnection();
AsyncEndPoint endp = http.getEndPoint();
Executor executor = http.getConnector().findExecutor();
final AsyncWebSocketConnection connection = new AsyncWebSocketConnection(endp,executor,policy);
endp.setAsyncConnection(connection);
// addConnection(connection);
// Initialize / Negotiate Extensions
List<Extension> extensions = initExtensions(extensionsRequested);
// Set the defaults
// connection.getConnection().setMaxBinaryMessageSize(_maxBinaryMessageSize);
// connection.getConnection().setMaxTextMessageSize(_maxTextMessageSize);
// Process (version specific) handshake response
handshaker.doHandshakeResponse(request,response,extensions,acceptedSubProtocol);
// Let the connection finish processing the handshake
// connection.handshake(request, response, protocol);
response.flushBuffer();
// Add connection
addConnection(connection);
// Give the connection any unused data from the HTTP connection.
// connection.fillBuffersFrom(((HttpParser)http.getParser()).getHeaderBuffer());
// connection.fillBuffersFrom(((HttpParser)http.getParser()).getBodyBuffer());
// Tell jetty about the new connection
LOG.debug("Websocket upgrade {} {} {} {}",request.getRequestURI(),version,acceptedSubProtocol,connection);
request.setAttribute("org.eclipse.jetty.io.Connection",connection); // TODO: this still needed?
// LOG.debug("Websocket upgrade {} {} {} {}",request.getRequestURI(),draft,protocol,connection);
// request.setAttribute("org.eclipse.jetty.io.Connection", connection);
}
}