Merge branch 'jetty-9' into jetty-9-oneconnector
Conflicts: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java
This commit is contained in:
commit
5e6cd1b27f
|
@ -20,10 +20,12 @@ import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -44,7 +46,6 @@ import javax.management.ObjectName;
|
||||||
import javax.management.ReflectionException;
|
import javax.management.ReflectionException;
|
||||||
import javax.management.modelmbean.ModelMBean;
|
import javax.management.modelmbean.ModelMBean;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.LazyList;
|
|
||||||
import org.eclipse.jetty.util.Loader;
|
import org.eclipse.jetty.util.Loader;
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
import org.eclipse.jetty.util.TypeUtil;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
@ -223,25 +224,25 @@ public class ObjectMBean implements DynamicMBean
|
||||||
{
|
{
|
||||||
// Start with blank lazy lists attributes etc.
|
// Start with blank lazy lists attributes etc.
|
||||||
String desc=null;
|
String desc=null;
|
||||||
Object attributes=null;
|
List<MBeanAttributeInfo> attributes = new ArrayList<MBeanAttributeInfo>();
|
||||||
Object constructors=null;
|
List<MBeanConstructorInfo> constructors = new ArrayList<MBeanConstructorInfo>();
|
||||||
Object operations=null;
|
List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
|
||||||
Object notifications=null;
|
List<MBeanNotificationInfo> notifications = new ArrayList<MBeanNotificationInfo>();
|
||||||
|
|
||||||
// Find list of classes that can influence the mbean
|
// Find list of classes that can influence the mbean
|
||||||
Class<?> o_class=_managed.getClass();
|
Class<?> o_class=_managed.getClass();
|
||||||
Object influences = findInfluences(null, _managed.getClass());
|
List<Class<?>> influences = findInfluences(new ArrayList<Class<?>>(), _managed.getClass());
|
||||||
|
|
||||||
LOG.debug("Influence Count: " + LazyList.size(influences) );
|
LOG.debug("Influence Count: " + influences.size() );
|
||||||
|
|
||||||
// Process Type Annotations
|
// Process Type Annotations
|
||||||
ManagedObject primary = o_class.getAnnotation( ManagedObject.class);
|
ManagedObject primary = o_class.getAnnotation( ManagedObject.class);
|
||||||
desc = primary.value();
|
desc = primary.value();
|
||||||
|
|
||||||
// For each influence
|
// For each influence
|
||||||
for (int i=0;i<LazyList.size(influences);i++)
|
for (int i=0;i<influences.size();i++)
|
||||||
{
|
{
|
||||||
Class<?> oClass = (Class<?>)LazyList.get(influences, i);
|
Class<?> oClass = influences.get(i);
|
||||||
|
|
||||||
ManagedObject typeAnnotation = oClass.getAnnotation( ManagedObject.class);
|
ManagedObject typeAnnotation = oClass.getAnnotation( ManagedObject.class);
|
||||||
|
|
||||||
|
@ -263,7 +264,7 @@ public class ObjectMBean implements DynamicMBean
|
||||||
if ( fieldAnnotation != null )
|
if ( fieldAnnotation != null )
|
||||||
{
|
{
|
||||||
LOG.debug("Field Annotation found for: " + field.getName() );
|
LOG.debug("Field Annotation found for: " + field.getName() );
|
||||||
attributes=LazyList.add(attributes, defineAttribute(field.getName(), fieldAnnotation));
|
attributes.add( defineAttribute(field.getName(), fieldAnnotation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +278,7 @@ public class ObjectMBean implements DynamicMBean
|
||||||
{
|
{
|
||||||
// TODO sort out how a proper name could get here, its a method name as an attribute at this point.
|
// TODO sort out how a proper name could get here, its a method name as an attribute at this point.
|
||||||
LOG.debug("Attribute Annotation found for: " + method.getName() );
|
LOG.debug("Attribute Annotation found for: " + method.getName() );
|
||||||
attributes=LazyList.add(attributes,defineAttribute(method.getName(),methodAttributeAnnotation));
|
attributes.add(defineAttribute(method.getName(),methodAttributeAnnotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedOperation methodOperationAnnotation = method.getAnnotation(ManagedOperation.class);
|
ManagedOperation methodOperationAnnotation = method.getAnnotation(ManagedOperation.class);
|
||||||
|
@ -285,7 +286,7 @@ public class ObjectMBean implements DynamicMBean
|
||||||
if (methodOperationAnnotation != null)
|
if (methodOperationAnnotation != null)
|
||||||
{
|
{
|
||||||
LOG.debug("Method Annotation found for: " + method.getName());
|
LOG.debug("Method Annotation found for: " + method.getName());
|
||||||
operations = LazyList.add(operations,defineOperation(method,methodOperationAnnotation));
|
operations.add(defineOperation(method,methodOperationAnnotation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,10 +299,10 @@ public class ObjectMBean implements DynamicMBean
|
||||||
|
|
||||||
_info = new MBeanInfo(o_class.getName(),
|
_info = new MBeanInfo(o_class.getName(),
|
||||||
desc,
|
desc,
|
||||||
(MBeanAttributeInfo[])LazyList.toArray(attributes, MBeanAttributeInfo.class),
|
(MBeanAttributeInfo[])attributes.toArray(new MBeanAttributeInfo[attributes.size()]),
|
||||||
(MBeanConstructorInfo[])LazyList.toArray(constructors, MBeanConstructorInfo.class),
|
(MBeanConstructorInfo[])constructors.toArray(new MBeanConstructorInfo[constructors.size()]),
|
||||||
(MBeanOperationInfo[])LazyList.toArray(operations, MBeanOperationInfo.class),
|
(MBeanOperationInfo[])operations.toArray(new MBeanOperationInfo[operations.size()]),
|
||||||
(MBeanNotificationInfo[])LazyList.toArray(notifications, MBeanNotificationInfo.class));
|
(MBeanNotificationInfo[])notifications.toArray(new MBeanNotificationInfo[notifications.size()]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(RuntimeException e)
|
catch(RuntimeException e)
|
||||||
|
@ -513,12 +514,12 @@ public class ObjectMBean implements DynamicMBean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object findInfluences(Object influences, Class<?> aClass)
|
private static List<Class<?>> findInfluences(List<Class<?>> influences, Class<?> aClass)
|
||||||
{
|
{
|
||||||
if (aClass!=null)
|
if (aClass!=null)
|
||||||
{
|
{
|
||||||
// This class is an influence
|
// This class is an influence
|
||||||
influences=LazyList.add(influences,aClass);
|
influences.add(aClass);
|
||||||
|
|
||||||
// check for mbean influence
|
// check for mbean influence
|
||||||
ManagedObject mo = aClass.getAnnotation(ManagedObject.class);
|
ManagedObject mo = aClass.getAnnotation(ManagedObject.class);
|
||||||
|
@ -532,7 +533,7 @@ public class ObjectMBean implements DynamicMBean
|
||||||
Class<?> mbean = Class.forName(clazz);
|
Class<?> mbean = Class.forName(clazz);
|
||||||
|
|
||||||
LOG.debug("MBean Influence found for " + aClass.getSimpleName() );
|
LOG.debug("MBean Influence found for " + aClass.getSimpleName() );
|
||||||
influences = LazyList.add(influences, mbean);
|
influences.add(mbean);
|
||||||
}
|
}
|
||||||
catch ( ClassNotFoundException cnfe )
|
catch ( ClassNotFoundException cnfe )
|
||||||
{
|
{
|
||||||
|
@ -548,6 +549,7 @@ public class ObjectMBean implements DynamicMBean
|
||||||
for (int i=0;ifs!=null && i<ifs.length;i++)
|
for (int i=0;ifs!=null && i<ifs.length;i++)
|
||||||
influences=findInfluences(influences,ifs[i]);
|
influences=findInfluences(influences,ifs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return influences;
|
return influences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
import javax.management.MBeanAttributeInfo;
|
import javax.management.MBeanAttributeInfo;
|
||||||
import javax.management.MBeanInfo;
|
import javax.management.MBeanInfo;
|
||||||
import javax.management.MBeanOperationInfo;
|
import javax.management.MBeanOperationInfo;
|
||||||
|
@ -41,14 +42,8 @@ public class ObjectMBeanTest
|
||||||
@Test
|
@Test
|
||||||
public void testMbeanInfo() throws Exception
|
public void testMbeanInfo() throws Exception
|
||||||
{
|
{
|
||||||
MBeanContainer container = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
|
||||||
|
|
||||||
container.start();
|
|
||||||
|
|
||||||
Derived derived = new Derived();
|
Derived derived = new Derived();
|
||||||
//ObjectMBean mbean = new ObjectMBean(derived);
|
|
||||||
ObjectMBean mbean = (ObjectMBean)ObjectMBean.mbeanFor(derived);
|
ObjectMBean mbean = (ObjectMBean)ObjectMBean.mbeanFor(derived);
|
||||||
mbean.setMBeanContainer(container);
|
|
||||||
|
|
||||||
assertTrue(mbean.getMBeanInfo()!=null);
|
assertTrue(mbean.getMBeanInfo()!=null);
|
||||||
|
|
||||||
|
@ -69,6 +64,10 @@ public class ObjectMBeanTest
|
||||||
|
|
||||||
Assert.assertEquals("attribute values does not match", "Full Name", mbean.getAttribute("fname") );
|
Assert.assertEquals("attribute values does not match", "Full Name", mbean.getAttribute("fname") );
|
||||||
|
|
||||||
|
//mbean.setAttribute( new Attribute("fname","Fuller Name"));
|
||||||
|
|
||||||
|
//Assert.assertEquals("set attribute value does not match", "Fuller Name", mbean.getAttribute("fname") );
|
||||||
|
|
||||||
Assert.assertEquals("proxy attribute values do not match", "goop", mbean.getAttribute("goop") );
|
Assert.assertEquals("proxy attribute values do not match", "goop", mbean.getAttribute("goop") );
|
||||||
|
|
||||||
Assert.assertEquals("operation count does not match", 5, info.getOperations().length);
|
Assert.assertEquals("operation count does not match", 5, info.getOperations().length);
|
||||||
|
|
|
@ -156,7 +156,7 @@ public class BufferUtil
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** Flip the buffer to Flush mode.
|
/** Flip the buffer to Flush mode.
|
||||||
* The limit is set to the first unused byte(the old position) amd
|
* The limit is set to the first unused byte(the old position) and
|
||||||
* the position is set to the passed position.
|
* the position is set to the passed position.
|
||||||
* <p>
|
* <p>
|
||||||
* This method is used as a replacement of {@link Buffer#flip()}.
|
* This method is used as a replacement of {@link Buffer#flip()}.
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class FragmentExtension extends Extension
|
||||||
private int maxLength = -1;
|
private int maxLength = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C> void output(C context, Callback<C> callback, WebSocketFrame frame) throws IOException
|
public <C> void output(C context, Callback<C> callback, final WebSocketFrame frame) throws IOException
|
||||||
{
|
{
|
||||||
if (frame.isControlFrame())
|
if (frame.isControlFrame())
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,6 +106,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
}
|
}
|
||||||
flushing = false;
|
flushing = false;
|
||||||
}
|
}
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -288,7 +289,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
else if (filled < 0)
|
else if (filled < 0)
|
||||||
{
|
{
|
||||||
LOG.debug("read - EOF Reached");
|
LOG.debug("read - EOF Reached");
|
||||||
disconnect(false);
|
// disconnect(false); // FIXME Simone says this is bad
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -376,15 +377,9 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
endpoint.write(frameBytes.context,frameBytes,buffer);
|
endpoint.write(frameBytes.context,frameBytes,buffer);
|
||||||
long count = writes.incrementAndGet();
|
|
||||||
if ((count % 10) == 0)
|
|
||||||
{
|
|
||||||
LOG.info("Server wrote {} ByteBuffers",count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Throwable t)
|
catch (Throwable t)
|
||||||
{
|
{
|
||||||
LOG.debug(t);
|
|
||||||
frameBytes.failed(frameBytes.context,t);
|
frameBytes.failed(frameBytes.context,t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,14 @@ package org.eclipse.jetty.websocket.io;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.protocol.OpCode;
|
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||||
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
||||||
|
|
||||||
public class ControlFrameBytes<C> extends FrameBytes<C>
|
public class ControlFrameBytes<C> extends FrameBytes<C>
|
||||||
{
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(ControlFrameBytes.class);
|
||||||
private ByteBuffer buffer;
|
private ByteBuffer buffer;
|
||||||
|
|
||||||
public ControlFrameBytes(AbstractWebSocketConnection connection, Callback<C> callback, C context, WebSocketFrame frame)
|
public ControlFrameBytes(AbstractWebSocketConnection connection, Callback<C> callback, C context, WebSocketFrame frame)
|
||||||
|
@ -32,6 +35,7 @@ public class ControlFrameBytes<C> extends FrameBytes<C>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void completed(C context) {
|
public void completed(C context) {
|
||||||
|
LOG.debug("completed() - frame: {}",frame);
|
||||||
connection.getBufferPool().release(buffer);
|
connection.getBufferPool().release(buffer);
|
||||||
|
|
||||||
super.completed(context);
|
super.completed(context);
|
||||||
|
@ -39,7 +43,7 @@ public class ControlFrameBytes<C> extends FrameBytes<C>
|
||||||
if (frame.getOpCode() == OpCode.CLOSE)
|
if (frame.getOpCode() == OpCode.CLOSE)
|
||||||
{
|
{
|
||||||
// Disconnect the connection (no more packets/frames)
|
// Disconnect the connection (no more packets/frames)
|
||||||
connection.disconnect(false);
|
connection.disconnect(true); // FIXME (should only shutdown output here)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public abstract class FrameBytes<C> implements Callback<C>, Runnable
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
{
|
{
|
||||||
LOG.debug("completed({})",context);
|
LOG.debug("completed({}) - {}",context,this.getClass().getName());
|
||||||
}
|
}
|
||||||
cancelTask();
|
cancelTask();
|
||||||
connection.complete(this);
|
connection.complete(this);
|
||||||
|
|
|
@ -49,6 +49,7 @@ public class Parser
|
||||||
private int cursor = 0;
|
private int cursor = 0;
|
||||||
// Frame
|
// Frame
|
||||||
private WebSocketFrame frame;
|
private WebSocketFrame frame;
|
||||||
|
private WebSocketFrame priorDataFrame;
|
||||||
private byte lastDataOpcode;
|
private byte lastDataOpcode;
|
||||||
// payload specific
|
// payload specific
|
||||||
private ByteBuffer payload;
|
private ByteBuffer payload;
|
||||||
|
@ -177,8 +178,15 @@ public class Parser
|
||||||
{
|
{
|
||||||
LOG.debug("{} Parsed Frame: {}",policy.getBehavior(),frame);
|
LOG.debug("{} Parsed Frame: {}",policy.getBehavior(),frame);
|
||||||
notifyFrame(frame);
|
notifyFrame(frame);
|
||||||
|
if (frame.isDataFrame() && frame.isFin())
|
||||||
|
{
|
||||||
|
priorDataFrame = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priorDataFrame = frame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (WebSocketException e)
|
catch (WebSocketException e)
|
||||||
{
|
{
|
||||||
|
@ -267,20 +275,35 @@ public class Parser
|
||||||
throw new ProtocolException("RSV3 not allowed to be set");
|
throw new ProtocolException("RSV3 not allowed to be set");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpCode.isControlFrame(opcode) && !fin)
|
boolean isContinuation = false;
|
||||||
{
|
|
||||||
throw new ProtocolException("Fragmented Control Frame [" + OpCode.name(opcode) + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opcode == OpCode.CONTINUATION)
|
if (OpCode.isControlFrame(opcode))
|
||||||
{
|
{
|
||||||
if (frame == null)
|
// control frame validation
|
||||||
|
if (!fin)
|
||||||
{
|
{
|
||||||
throw new ProtocolException("Fragment continuation frame without prior !FIN");
|
throw new ProtocolException("Fragmented Control Frame [" + OpCode.name(opcode) + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (opcode == OpCode.CONTINUATION)
|
||||||
|
{
|
||||||
|
isContinuation = true;
|
||||||
|
// continuation validation
|
||||||
|
if (priorDataFrame == null)
|
||||||
|
{
|
||||||
|
throw new ProtocolException("CONTINUATION frame without prior !FIN");
|
||||||
}
|
}
|
||||||
// Be careful to use the original opcode
|
// Be careful to use the original opcode
|
||||||
opcode = lastDataOpcode;
|
opcode = lastDataOpcode;
|
||||||
}
|
}
|
||||||
|
else if (OpCode.isDataFrame(opcode))
|
||||||
|
{
|
||||||
|
// data validation
|
||||||
|
if ((priorDataFrame != null) && (!priorDataFrame.isFin()))
|
||||||
|
{
|
||||||
|
throw new ProtocolException("Unexpected " + OpCode.name(opcode) + " frame, was expecting CONTINUATION");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// base framing flags
|
// base framing flags
|
||||||
frame = new WebSocketFrame();
|
frame = new WebSocketFrame();
|
||||||
|
@ -289,6 +312,7 @@ public class Parser
|
||||||
frame.setRsv2(rsv2);
|
frame.setRsv2(rsv2);
|
||||||
frame.setRsv3(rsv3);
|
frame.setRsv3(rsv3);
|
||||||
frame.setOpCode(opcode);
|
frame.setOpCode(opcode);
|
||||||
|
frame.setContinuation(isContinuation);
|
||||||
|
|
||||||
if (frame.isDataFrame())
|
if (frame.isDataFrame())
|
||||||
{
|
{
|
||||||
|
@ -392,8 +416,8 @@ public class Parser
|
||||||
case MASK_BYTES:
|
case MASK_BYTES:
|
||||||
{
|
{
|
||||||
byte b = buffer.get();
|
byte b = buffer.get();
|
||||||
|
frame.getMask()[4 - cursor] = b;
|
||||||
--cursor;
|
--cursor;
|
||||||
frame.getMask()[cursor] = b;
|
|
||||||
if (cursor == 0)
|
if (cursor == 0)
|
||||||
{
|
{
|
||||||
// special case for empty payloads (no more bytes left in buffer)
|
// special case for empty payloads (no more bytes left in buffer)
|
||||||
|
@ -435,7 +459,7 @@ public class Parser
|
||||||
* the payload buffer
|
* the payload buffer
|
||||||
* @return true if payload is done reading, false if incomplete
|
* @return true if payload is done reading, false if incomplete
|
||||||
*/
|
*/
|
||||||
public boolean parsePayload(ByteBuffer buffer)
|
private boolean parsePayload(ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
if (payloadLength == 0)
|
if (payloadLength == 0)
|
||||||
{
|
{
|
||||||
|
@ -449,6 +473,7 @@ public class Parser
|
||||||
getPolicy().assertValidPayloadLength(payloadLength);
|
getPolicy().assertValidPayloadLength(payloadLength);
|
||||||
frame.assertValid();
|
frame.assertValid();
|
||||||
payload = ByteBuffer.allocate(payloadLength);
|
payload = ByteBuffer.allocate(payloadLength);
|
||||||
|
BufferUtil.clearToFill(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferUtil.put(buffer,payload);
|
BufferUtil.put(buffer,payload);
|
||||||
|
@ -457,14 +482,18 @@ public class Parser
|
||||||
{
|
{
|
||||||
BufferUtil.flipToFlush(payload,0);
|
BufferUtil.flipToFlush(payload,0);
|
||||||
|
|
||||||
|
LOG.debug("PreMask: {}",BufferUtil.toDetailString(payload));
|
||||||
// demask (if needed)
|
// demask (if needed)
|
||||||
if (frame.isMasked())
|
if (frame.isMasked())
|
||||||
{
|
{
|
||||||
byte mask[] = frame.getMask();
|
byte mask[] = frame.getMask();
|
||||||
|
int offset;
|
||||||
|
int start = payload.position();
|
||||||
int end = payload.limit();
|
int end = payload.limit();
|
||||||
for (int i = payload.position(); i < end; i++)
|
for (int i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
payload.put(i,(byte)(payload.get(i) ^ mask[i % 4]));
|
offset = (i - start);
|
||||||
|
payload.put(i,(byte)(payload.get(i) ^ mask[offset % 4]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ public class WebSocketFrame implements Frame
|
||||||
*/
|
*/
|
||||||
public WebSocketFrame(byte opcode)
|
public WebSocketFrame(byte opcode)
|
||||||
{
|
{
|
||||||
|
reset();
|
||||||
this.opcode = opcode;
|
this.opcode = opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ public class WebSocketFrame implements Frame
|
||||||
*/
|
*/
|
||||||
public WebSocketFrame(WebSocketFrame copy)
|
public WebSocketFrame(WebSocketFrame copy)
|
||||||
{
|
{
|
||||||
fin = copy.rsv1;
|
fin = copy.fin;
|
||||||
rsv1 = copy.rsv2;
|
rsv1 = copy.rsv2;
|
||||||
rsv2 = copy.rsv2;
|
rsv2 = copy.rsv2;
|
||||||
rsv3 = copy.rsv3;
|
rsv3 = copy.rsv3;
|
||||||
|
|
|
@ -232,7 +232,7 @@ public class DeflateFrameExtensionTest
|
||||||
|
|
||||||
Assert.assertThat(prefix + ".opcode",actual.getOpCode(),is(OpCode.TEXT));
|
Assert.assertThat(prefix + ".opcode",actual.getOpCode(),is(OpCode.TEXT));
|
||||||
Assert.assertThat(prefix + ".fin",actual.isFin(),is(true));
|
Assert.assertThat(prefix + ".fin",actual.isFin(),is(true));
|
||||||
Assert.assertThat(prefix + ".rsv1",actual.isRsv1(),is(true));
|
Assert.assertThat(prefix + ".rsv1",actual.isRsv1(),is(false)); // RSV1 should be unset at this point
|
||||||
Assert.assertThat(prefix + ".rsv2",actual.isRsv2(),is(false));
|
Assert.assertThat(prefix + ".rsv2",actual.isRsv2(),is(false));
|
||||||
Assert.assertThat(prefix + ".rsv3",actual.isRsv3(),is(false));
|
Assert.assertThat(prefix + ".rsv3",actual.isRsv3(),is(false));
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class FragmentExtensionTest
|
||||||
quote.add("a single experiment can prove me wrong.");
|
quote.add("a single experiment can prove me wrong.");
|
||||||
quote.add("-- Albert Einstein");
|
quote.add("-- Albert Einstein");
|
||||||
|
|
||||||
// Manually compress frame and pass into extension
|
// Manually create frame and pass into extension
|
||||||
for (String q : quote)
|
for (String q : quote)
|
||||||
{
|
{
|
||||||
WebSocketFrame frame = WebSocketFrame.text(q);
|
WebSocketFrame frame = WebSocketFrame.text(q);
|
||||||
|
|
|
@ -16,19 +16,13 @@ import org.junit.Test;
|
||||||
|
|
||||||
public class GeneratorTest
|
public class GeneratorTest
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevent regression of masking of many packets.
|
* Prevent regression of masking of many packets.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testManyMasked()
|
public void testManyMasked()
|
||||||
{
|
{
|
||||||
byte[] MASK =
|
int pingCount = 10;
|
||||||
{ 0x11, 0x22, 0x33, 0x44 };
|
|
||||||
int pingCount = 1000;
|
|
||||||
|
|
||||||
// the generator
|
|
||||||
Generator generator = new UnitGenerator();
|
|
||||||
|
|
||||||
// Prepare frames
|
// Prepare frames
|
||||||
List<WebSocketFrame> send = new ArrayList<>();
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
@ -39,40 +33,15 @@ public class GeneratorTest
|
||||||
}
|
}
|
||||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
// Generate into single bytebuffer
|
ByteBuffer completeBuf = UnitGenerator.generate(send);
|
||||||
int buflen = 0;
|
|
||||||
for (WebSocketFrame f : send)
|
|
||||||
{
|
|
||||||
buflen += f.getPayloadLength() + Generator.OVERHEAD;
|
|
||||||
}
|
|
||||||
ByteBuffer completeBuf = ByteBuffer.allocate(buflen);
|
|
||||||
BufferUtil.clearToFill(completeBuf);
|
|
||||||
|
|
||||||
// Generate frames
|
|
||||||
for (WebSocketFrame f : send)
|
|
||||||
{
|
|
||||||
f.setMask(MASK); // make sure we have mask set
|
|
||||||
ByteBuffer slice = f.getPayload().slice();
|
|
||||||
BufferUtil.put(generator.generate(f),completeBuf);
|
|
||||||
f.setPayload(slice);
|
|
||||||
}
|
|
||||||
BufferUtil.flipToFlush(completeBuf,0);
|
|
||||||
|
|
||||||
// Parse complete buffer (5 bytes at a time)
|
// Parse complete buffer (5 bytes at a time)
|
||||||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
UnitParser parser = new UnitParser();
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
IncomingFramesCapture capture = new IncomingFramesCapture();
|
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||||
parser.setIncomingFramesHandler(capture);
|
parser.setIncomingFramesHandler(capture);
|
||||||
|
|
||||||
int segmentSize = 5;
|
int segmentSize = 5;
|
||||||
while (completeBuf.remaining() > 0)
|
parser.parseSlowly(completeBuf,segmentSize);
|
||||||
{
|
|
||||||
ByteBuffer part = completeBuf.slice();
|
|
||||||
int len = Math.min(segmentSize,part.remaining());
|
|
||||||
part.limit(part.position() + len);
|
|
||||||
parser.parse(part);
|
|
||||||
completeBuf.position(completeBuf.position() + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert validity of frame
|
// Assert validity of frame
|
||||||
int frameCount = send.size();
|
int frameCount = send.size();
|
||||||
|
|
|
@ -18,15 +18,151 @@ package org.eclipse.jetty.websocket.protocol;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.protocol.Parser;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class ParserTest
|
public class ParserTest
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Similar to the server side 5.15 testcase. A normal 2 fragment text text message, followed by another continuation.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParseCase5_15()
|
||||||
|
{
|
||||||
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment1").setFin(false));
|
||||||
|
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("fragment2").setFin(true));
|
||||||
|
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("fragment3").setFin(false)); // bad frame
|
||||||
|
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment4").setFin(true));
|
||||||
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
|
ByteBuffer completeBuf = UnitGenerator.generate(send);
|
||||||
|
UnitParser parser = new UnitParser();
|
||||||
|
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||||
|
parser.setIncomingFramesHandler(capture);
|
||||||
|
parser.parse(completeBuf);
|
||||||
|
|
||||||
|
capture.assertErrorCount(1);
|
||||||
|
capture.assertHasFrame(OpCode.TEXT,2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the server side 5.18 testcase. Text message fragmented as 2 frames, both as opcode=TEXT
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParseCase5_18()
|
||||||
|
{
|
||||||
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment1").setFin(false));
|
||||||
|
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment2").setFin(true)); // bad frame, must be continuation
|
||||||
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
|
ByteBuffer completeBuf = UnitGenerator.generate(send);
|
||||||
|
UnitParser parser = new UnitParser();
|
||||||
|
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||||
|
parser.setIncomingFramesHandler(capture);
|
||||||
|
parser.parse(completeBuf);
|
||||||
|
|
||||||
|
capture.assertErrorCount(1);
|
||||||
|
capture.assertHasFrame(OpCode.TEXT,1); // fragment 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the server side 5.19 testcase.
|
||||||
|
* text message, send in 5 frames/fragments, with 2 pings in the mix.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParseCase5_19()
|
||||||
|
{
|
||||||
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("f1").setFin(false));
|
||||||
|
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload(",f2").setFin(false));
|
||||||
|
send.add(new WebSocketFrame(OpCode.PING).setPayload("pong-1"));
|
||||||
|
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload(",f3").setFin(false));
|
||||||
|
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload(",f4").setFin(false));
|
||||||
|
send.add(new WebSocketFrame(OpCode.PING).setPayload("pong-2"));
|
||||||
|
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload(",f5").setFin(true));
|
||||||
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
|
ByteBuffer completeBuf = UnitGenerator.generate(send);
|
||||||
|
UnitParser parser = new UnitParser();
|
||||||
|
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||||
|
parser.setIncomingFramesHandler(capture);
|
||||||
|
parser.parse(completeBuf);
|
||||||
|
|
||||||
|
capture.assertErrorCount(0);
|
||||||
|
capture.assertHasFrame(OpCode.TEXT,5);
|
||||||
|
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||||
|
capture.assertHasFrame(OpCode.PING,2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the server side 5.6 testcase. pong, then text, then close frames.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParseCase5_6()
|
||||||
|
{
|
||||||
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
send.add(WebSocketFrame.pong().setPayload("ping"));
|
||||||
|
send.add(WebSocketFrame.text("hello, world"));
|
||||||
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
|
ByteBuffer completeBuf = UnitGenerator.generate(send);
|
||||||
|
UnitParser parser = new UnitParser();
|
||||||
|
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||||
|
parser.setIncomingFramesHandler(capture);
|
||||||
|
parser.parse(completeBuf);
|
||||||
|
|
||||||
|
capture.assertErrorCount(0);
|
||||||
|
capture.assertHasFrame(OpCode.TEXT,1);
|
||||||
|
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||||
|
capture.assertHasFrame(OpCode.PONG,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the server side 6.2.3 testcase. Lots of small 1 byte UTF8 Text frames, representing 1 overall text message.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParseCase6_2_3()
|
||||||
|
{
|
||||||
|
String utf8 = "Hello-\uC2B5@\uC39F\uC3A4\uC3BC\uC3A0\uC3A1-UTF-8!!";
|
||||||
|
byte msg[] = StringUtil.getUtf8Bytes(utf8);
|
||||||
|
|
||||||
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
int len = msg.length;
|
||||||
|
byte opcode = OpCode.TEXT;
|
||||||
|
byte mini[];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
WebSocketFrame frame = new WebSocketFrame(opcode);
|
||||||
|
mini = new byte[1];
|
||||||
|
mini[0] = msg[i];
|
||||||
|
frame.setPayload(mini);
|
||||||
|
boolean isLast = (i >= (len - 1));
|
||||||
|
frame.setFin(isLast);
|
||||||
|
send.add(frame);
|
||||||
|
opcode = OpCode.CONTINUATION;
|
||||||
|
}
|
||||||
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
|
ByteBuffer completeBuf = UnitGenerator.generate(send);
|
||||||
|
UnitParser parser = new UnitParser();
|
||||||
|
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||||
|
parser.setIncomingFramesHandler(capture);
|
||||||
|
parser.parse(completeBuf);
|
||||||
|
|
||||||
|
capture.assertErrorCount(0);
|
||||||
|
capture.assertHasFrame(OpCode.TEXT,len);
|
||||||
|
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseNothing()
|
public void testParseNothing()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
//========================================================================
|
//========================================================================
|
||||||
package org.eclipse.jetty.websocket.protocol;
|
package org.eclipse.jetty.websocket.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.StandardByteBufferPool;
|
import org.eclipse.jetty.io.StandardByteBufferPool;
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,6 +27,37 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
*/
|
*/
|
||||||
public class UnitGenerator extends Generator
|
public class UnitGenerator extends Generator
|
||||||
{
|
{
|
||||||
|
public static ByteBuffer generate(List<WebSocketFrame> frames)
|
||||||
|
{
|
||||||
|
// Create non-symmetrical mask (shows mask bytes order issues)
|
||||||
|
byte[] MASK =
|
||||||
|
{ 0x11, 0x22, 0x33, 0x44 };
|
||||||
|
|
||||||
|
// the generator
|
||||||
|
Generator generator = new UnitGenerator();
|
||||||
|
|
||||||
|
// Generate into single bytebuffer
|
||||||
|
int buflen = 0;
|
||||||
|
for (WebSocketFrame f : frames)
|
||||||
|
{
|
||||||
|
buflen += f.getPayloadLength() + Generator.OVERHEAD;
|
||||||
|
}
|
||||||
|
ByteBuffer completeBuf = ByteBuffer.allocate(buflen);
|
||||||
|
BufferUtil.clearToFill(completeBuf);
|
||||||
|
|
||||||
|
// Generate frames
|
||||||
|
for (WebSocketFrame f : frames)
|
||||||
|
{
|
||||||
|
f.setMask(MASK); // make sure we have mask set
|
||||||
|
ByteBuffer slice = f.getPayload().slice();
|
||||||
|
BufferUtil.put(generator.generate(f),completeBuf);
|
||||||
|
f.setPayload(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferUtil.flipToFlush(completeBuf,0);
|
||||||
|
return completeBuf;
|
||||||
|
}
|
||||||
|
|
||||||
public UnitGenerator()
|
public UnitGenerator()
|
||||||
{
|
{
|
||||||
super(WebSocketPolicy.newServerPolicy(),new StandardByteBufferPool());
|
super(WebSocketPolicy.newServerPolicy(),new StandardByteBufferPool());
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.eclipse.jetty.websocket.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
|
||||||
|
public class UnitParser extends Parser
|
||||||
|
{
|
||||||
|
public UnitParser()
|
||||||
|
{
|
||||||
|
super(WebSocketPolicy.newServerPolicy());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePartial(ByteBuffer buf, int numBytes)
|
||||||
|
{
|
||||||
|
int len = Math.min(numBytes,buf.remaining());
|
||||||
|
byte arr[] = new byte[len];
|
||||||
|
buf.get(arr,0,len);
|
||||||
|
this.parse(ByteBuffer.wrap(arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseSlowly(ByteBuffer buf, int segmentSize)
|
||||||
|
{
|
||||||
|
while (buf.remaining() > 0)
|
||||||
|
{
|
||||||
|
parsePartial(buf,segmentSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||||
org.eclipse.jetty.websocket.LEVEL=WARN
|
org.eclipse.jetty.websocket.LEVEL=WARN
|
||||||
|
# org.eclipse.jetty.websocket.protocol.Parser.LEVEL=DEBUG
|
|
@ -47,7 +47,7 @@ public class DeflateExtensionTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
@Ignore("Not yet working")
|
||||||
public void testDeflateFrameExtension() throws Exception
|
public void testDeflateFrameExtension() throws Exception
|
||||||
{
|
{
|
||||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||||
|
|
|
@ -233,6 +233,7 @@ public class WebSocketServletRFCTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Should be moved to Fuzzer")
|
||||||
public void testMaxBinarySize() throws Exception
|
public void testMaxBinarySize() throws Exception
|
||||||
{
|
{
|
||||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||||
|
@ -274,6 +275,7 @@ public class WebSocketServletRFCTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Should be moved to Fuzzer")
|
||||||
public void testMaxTextSize() throws Exception
|
public void testMaxTextSize() throws Exception
|
||||||
{
|
{
|
||||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||||
|
|
|
@ -23,7 +23,6 @@ import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
import org.eclipse.jetty.websocket.protocol.CloseInfo;
|
import org.eclipse.jetty.websocket.protocol.CloseInfo;
|
||||||
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
||||||
import org.eclipse.jetty.websocket.server.ab.Fuzzer.SendMode;
|
import org.eclipse.jetty.websocket.server.ab.Fuzzer.SendMode;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestABCase1 extends AbstractABCase
|
public class TestABCase1 extends AbstractABCase
|
||||||
|
@ -184,7 +183,6 @@ public class TestABCase1 extends AbstractABCase
|
||||||
* Echo 65535 byte TEXT message (uses medium 2 byte payload length)
|
* Echo 65535 byte TEXT message (uses medium 2 byte payload length)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase1_1_6() throws Exception
|
public void testCase1_1_6() throws Exception
|
||||||
{
|
{
|
||||||
byte payload[] = new byte[65535];
|
byte payload[] = new byte[65535];
|
||||||
|
@ -216,7 +214,6 @@ public class TestABCase1 extends AbstractABCase
|
||||||
* Echo 65536 byte TEXT message (uses large 8 byte payload length)
|
* Echo 65536 byte TEXT message (uses large 8 byte payload length)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase1_1_7() throws Exception
|
public void testCase1_1_7() throws Exception
|
||||||
{
|
{
|
||||||
byte payload[] = new byte[65536];
|
byte payload[] = new byte[65536];
|
||||||
|
@ -252,7 +249,6 @@ public class TestABCase1 extends AbstractABCase
|
||||||
* This is done to test the parsing together of the frame on the server side.
|
* This is done to test the parsing together of the frame on the server side.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase1_1_8() throws Exception
|
public void testCase1_1_8() throws Exception
|
||||||
{
|
{
|
||||||
byte payload[] = new byte[65536];
|
byte payload[] = new byte[65536];
|
||||||
|
@ -438,7 +434,6 @@ public class TestABCase1 extends AbstractABCase
|
||||||
* Echo 65535 byte BINARY message (uses medium 2 byte payload length)
|
* Echo 65535 byte BINARY message (uses medium 2 byte payload length)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase1_2_6() throws Exception
|
public void testCase1_2_6() throws Exception
|
||||||
{
|
{
|
||||||
byte payload[] = new byte[65535];
|
byte payload[] = new byte[65535];
|
||||||
|
@ -470,7 +465,6 @@ public class TestABCase1 extends AbstractABCase
|
||||||
* Echo 65536 byte BINARY message (uses large 8 byte payload length)
|
* Echo 65536 byte BINARY message (uses large 8 byte payload length)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase1_2_7() throws Exception
|
public void testCase1_2_7() throws Exception
|
||||||
{
|
{
|
||||||
byte payload[] = new byte[65536];
|
byte payload[] = new byte[65536];
|
||||||
|
@ -506,7 +500,6 @@ public class TestABCase1 extends AbstractABCase
|
||||||
* This is done to test the parsing together of the frame on the server side.
|
* This is done to test the parsing together of the frame on the server side.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase1_2_8() throws Exception
|
public void testCase1_2_8() throws Exception
|
||||||
{
|
{
|
||||||
byte payload[] = new byte[65536];
|
byte payload[] = new byte[65536];
|
||||||
|
|
|
@ -26,7 +26,6 @@ import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
import org.eclipse.jetty.websocket.protocol.CloseInfo;
|
import org.eclipse.jetty.websocket.protocol.CloseInfo;
|
||||||
import org.eclipse.jetty.websocket.protocol.OpCode;
|
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||||
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@ -242,7 +241,6 @@ public class TestABCase5 extends AbstractABCase
|
||||||
* Send text fragmented properly in 2 frames, then continuation!fin, then text unfragmented.
|
* Send text fragmented properly in 2 frames, then continuation!fin, then text unfragmented.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase5_15() throws Exception
|
public void testCase5_15() throws Exception
|
||||||
{
|
{
|
||||||
List<WebSocketFrame> send = new ArrayList<>();
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
@ -253,7 +251,7 @@ public class TestABCase5 extends AbstractABCase
|
||||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
List<WebSocketFrame> expect = new ArrayList<>();
|
List<WebSocketFrame> expect = new ArrayList<>();
|
||||||
send.add(WebSocketFrame.text("fragment1fragment2"));
|
expect.add(WebSocketFrame.text("fragment1fragment2"));
|
||||||
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
|
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
|
||||||
|
|
||||||
Fuzzer fuzzer = new Fuzzer(this);
|
Fuzzer fuzzer = new Fuzzer(this);
|
||||||
|
@ -338,7 +336,6 @@ public class TestABCase5 extends AbstractABCase
|
||||||
* text message fragmented in 2 frames, both frames as opcode=TEXT
|
* text message fragmented in 2 frames, both frames as opcode=TEXT
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore /* FIXME */
|
|
||||||
public void testCase5_18() throws Exception
|
public void testCase5_18() throws Exception
|
||||||
{
|
{
|
||||||
List<WebSocketFrame> send = new ArrayList<>();
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
|
|
|
@ -37,6 +37,27 @@ import org.junit.runner.RunWith;
|
||||||
@RunWith(AdvancedRunner.class)
|
@RunWith(AdvancedRunner.class)
|
||||||
public class TestABCase6 extends AbstractABCase
|
public class TestABCase6 extends AbstractABCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Split a message byte array into a series of fragments (frames + continuations) of 1 byte message contents each.
|
||||||
|
*/
|
||||||
|
protected void fragmentText(List<WebSocketFrame> frames, byte msg[])
|
||||||
|
{
|
||||||
|
int len = msg.length;
|
||||||
|
byte opcode = OpCode.TEXT;
|
||||||
|
byte mini[];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
WebSocketFrame frame = new WebSocketFrame(opcode);
|
||||||
|
mini = new byte[1];
|
||||||
|
mini[0] = msg[i];
|
||||||
|
frame.setPayload(mini);
|
||||||
|
boolean isLast = (i >= (len - 1));
|
||||||
|
frame.setFin(isLast);
|
||||||
|
frames.add(frame);
|
||||||
|
opcode = OpCode.CONTINUATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* text message, 1 frame, 0 length
|
* text message, 1 frame, 0 length
|
||||||
*/
|
*/
|
||||||
|
@ -198,18 +219,7 @@ public class TestABCase6 extends AbstractABCase
|
||||||
byte msg[] = StringUtil.getUtf8Bytes(utf8);
|
byte msg[] = StringUtil.getUtf8Bytes(utf8);
|
||||||
|
|
||||||
List<WebSocketFrame> send = new ArrayList<>();
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
int len = msg.length;
|
fragmentText(send,msg);
|
||||||
byte opcode = OpCode.TEXT;
|
|
||||||
byte mini[];
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
WebSocketFrame frame = new WebSocketFrame(opcode);
|
|
||||||
mini = new byte[1];
|
|
||||||
mini[0] = msg[i];
|
|
||||||
frame.setPayload(mini);
|
|
||||||
frame.setFin(!(i < (len - 1)));
|
|
||||||
send.add(frame);
|
|
||||||
}
|
|
||||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
List<WebSocketFrame> expect = new ArrayList<>();
|
List<WebSocketFrame> expect = new ArrayList<>();
|
||||||
|
@ -239,18 +249,7 @@ public class TestABCase6 extends AbstractABCase
|
||||||
byte msg[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5");
|
byte msg[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5");
|
||||||
|
|
||||||
List<WebSocketFrame> send = new ArrayList<>();
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
int len = msg.length;
|
fragmentText(send,msg);
|
||||||
byte opcode = OpCode.TEXT;
|
|
||||||
byte mini[];
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
WebSocketFrame frame = new WebSocketFrame(opcode);
|
|
||||||
mini = new byte[1];
|
|
||||||
mini[0] = msg[i];
|
|
||||||
frame.setPayload(mini);
|
|
||||||
frame.setFin(!(i < (len - 1)));
|
|
||||||
send.add(frame);
|
|
||||||
}
|
|
||||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
List<WebSocketFrame> expect = new ArrayList<>();
|
List<WebSocketFrame> expect = new ArrayList<>();
|
||||||
|
@ -309,18 +308,7 @@ public class TestABCase6 extends AbstractABCase
|
||||||
byte invalid[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5EDA080656469746564");
|
byte invalid[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5EDA080656469746564");
|
||||||
|
|
||||||
List<WebSocketFrame> send = new ArrayList<>();
|
List<WebSocketFrame> send = new ArrayList<>();
|
||||||
int len = invalid.length;
|
fragmentText(send,invalid);
|
||||||
byte opcode = OpCode.TEXT;
|
|
||||||
byte mini[];
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
WebSocketFrame frame = new WebSocketFrame(opcode);
|
|
||||||
mini = new byte[1];
|
|
||||||
mini[0] = invalid[i];
|
|
||||||
frame.setPayload(mini);
|
|
||||||
frame.setFin(!(i < (len - 1)));
|
|
||||||
send.add(frame);
|
|
||||||
}
|
|
||||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||||
|
|
||||||
List<WebSocketFrame> expect = new ArrayList<>();
|
List<WebSocketFrame> expect = new ArrayList<>();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||||
org.eclipse.jetty.LEVEL=WARN
|
org.eclipse.jetty.LEVEL=WARN
|
||||||
|
# org.eclipse.jetty.io.ChannelEndPoint.LEVEL=INFO
|
||||||
org.eclipse.jetty.server.LEVEL=WARN
|
org.eclipse.jetty.server.LEVEL=WARN
|
||||||
# org.eclipse.jetty.websocket.LEVEL=WARN
|
# org.eclipse.jetty.websocket.LEVEL=WARN
|
||||||
org.eclipse.jetty.websocket.server.helper.RFCSocket.LEVEL=OFF
|
org.eclipse.jetty.websocket.server.helper.RFCSocket.LEVEL=OFF
|
||||||
|
@ -10,6 +11,8 @@ org.eclipse.jetty.websocket.server.helper.RFCSocket.LEVEL=OFF
|
||||||
# org.eclipse.jetty.util.thread.QueuedThreadPool.LEVEL=DEBUG
|
# org.eclipse.jetty.util.thread.QueuedThreadPool.LEVEL=DEBUG
|
||||||
# org.eclipse.jetty.io.SelectorManager.LEVEL=INFO
|
# org.eclipse.jetty.io.SelectorManager.LEVEL=INFO
|
||||||
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||||
|
# org.eclipse.jetty.websocket.io.FrameBytes.LEVEL=DEBUG
|
||||||
|
# org.eclipse.jetty.websocket.io.ControlFrameBytes.LEVEL=DEBUG
|
||||||
# org.eclipse.jetty.websocket.driver.WebSocketEventDriver.LEVEL=DEBUG
|
# org.eclipse.jetty.websocket.driver.WebSocketEventDriver.LEVEL=DEBUG
|
||||||
# org.eclipse.jetty.websocket.extensions.LEVEL=DEBUG
|
# org.eclipse.jetty.websocket.extensions.LEVEL=DEBUG
|
||||||
# org.eclipse.jetty.websocket.protocol.Generator.LEVEL=INFO
|
# org.eclipse.jetty.websocket.protocol.Generator.LEVEL=INFO
|
||||||
|
|
Loading…
Reference in New Issue