some frame consolidation work in progress
This commit is contained in:
parent
aaf27d7e2a
commit
f4a644347b
|
@ -5,7 +5,6 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.jetty.websocket.frames.BinaryFrame;
|
||||
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.ContinuationFrame;
|
||||
import org.eclipse.jetty.websocket.frames.PingFrame;
|
||||
import org.eclipse.jetty.websocket.frames.PongFrame;
|
||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
||||
|
|
|
@ -37,8 +37,6 @@ public class BaseFrame
|
|||
private int payloadLength;
|
||||
private byte mask[];
|
||||
|
||||
// internal tracking
|
||||
private int continuationIndex = 0;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
|
@ -55,19 +53,7 @@ public class BaseFrame
|
|||
this.opcode = opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of fragments this frame consists of.
|
||||
* <p>
|
||||
* For every {@link OpCode#CONTINUATION} opcode encountered, this increments by one.
|
||||
* <p>
|
||||
* Note: Not part of the Base Framing Protocol / header information.
|
||||
*
|
||||
* @return the number of continuation fragments encountered.
|
||||
*/
|
||||
public int getContinuationIndex()
|
||||
{
|
||||
return continuationIndex;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getMask()
|
||||
{
|
||||
|
@ -128,13 +114,8 @@ public class BaseFrame
|
|||
masked = false;
|
||||
payloadLength = -1;
|
||||
mask = null;
|
||||
continuationIndex = 0;
|
||||
}
|
||||
|
||||
public void setContinuationIndex(int continuationIndex)
|
||||
{
|
||||
this.continuationIndex = continuationIndex;
|
||||
}
|
||||
|
||||
public void setFin(boolean fin)
|
||||
{
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.eclipse.jetty.websocket.api.OpCode;
|
|||
*/
|
||||
public class BinaryFrame extends DataFrame
|
||||
{
|
||||
private ByteBuffer data; // TODO: make this a standard byte buffer?
|
||||
|
||||
/**
|
||||
* Default unspecified data
|
||||
|
@ -20,45 +19,20 @@ public class BinaryFrame extends DataFrame
|
|||
super(OpCode.BINARY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data
|
||||
*
|
||||
* @return the raw bytebuffer data (can be null)
|
||||
*/
|
||||
public ByteBuffer getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpCode getOpCode()
|
||||
{
|
||||
return OpCode.BINARY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data and payload length.
|
||||
*
|
||||
* @param buf
|
||||
* the bytebuffer to set
|
||||
*/
|
||||
public void setData(byte buf[])
|
||||
{
|
||||
int len = buf.length;
|
||||
this.data = ByteBuffer.allocate(len);
|
||||
this.setPayloadLength(len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data and payload length.
|
||||
*
|
||||
* @param buf
|
||||
* the byte array to set
|
||||
*/
|
||||
public void setData(ByteBuffer buffer)
|
||||
|
||||
|
||||
@Override
|
||||
public void setPayload(ByteBuffer buffer)
|
||||
{
|
||||
this.data = buffer;
|
||||
this.setPayloadLength(buffer.capacity());
|
||||
// TODO Auto-generated method stub
|
||||
super.setPayload(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,7 +41,7 @@ public class BinaryFrame extends DataFrame
|
|||
StringBuilder b = new StringBuilder();
|
||||
b.append("BinaryFrame[");
|
||||
b.append("len=").append(getPayloadLength());
|
||||
b.append(",data=").append(BufferUtil.toDetailString(getData()));
|
||||
b.append(",data=").append(BufferUtil.toDetailString(getPayload()));
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
public class ContinuationFrame extends BaseFrame
|
||||
{
|
||||
public ContinuationFrame()
|
||||
{
|
||||
super(OpCode.CONTINUATION);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,16 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
public abstract class DataFrame extends BaseFrame
|
||||
{
|
||||
// internal tracking
|
||||
private int continuationIndex = 0;
|
||||
private boolean continuation = false;
|
||||
private ByteBuffer payload;
|
||||
|
||||
public DataFrame()
|
||||
{
|
||||
super();
|
||||
|
@ -13,4 +20,78 @@ public abstract class DataFrame extends BaseFrame
|
|||
{
|
||||
super(opcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data
|
||||
*
|
||||
* @return the raw bytebuffer data (can be null)
|
||||
*/
|
||||
public ByteBuffer getPayload()
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data and payload length.
|
||||
*
|
||||
* @param buf
|
||||
* the bytebuffer to set
|
||||
*/
|
||||
protected void setPayload(byte buf[])
|
||||
{
|
||||
int len = buf.length;
|
||||
this.payload = ByteBuffer.allocate(len);
|
||||
this.setPayloadLength(len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the data and payload length.
|
||||
*
|
||||
* @param buf
|
||||
* the byte array to set
|
||||
*/
|
||||
protected void setPayload(ByteBuffer buffer)
|
||||
{
|
||||
this.payload = buffer;
|
||||
this.setPayloadLength(buffer.capacity());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The number of fragments this frame consists of.
|
||||
* <p>
|
||||
* For every {@link OpCode#CONTINUATION} opcode encountered, this increments by one.
|
||||
* <p>
|
||||
* Note: Not part of the Base Framing Protocol / header information.
|
||||
*
|
||||
* @return the number of continuation fragments encountered.
|
||||
*/
|
||||
public int getContinuationIndex()
|
||||
{
|
||||
return continuationIndex;
|
||||
}
|
||||
|
||||
public void setContinuationIndex(int continuationIndex)
|
||||
{
|
||||
this.continuationIndex = continuationIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
continuationIndex = 0;
|
||||
}
|
||||
|
||||
public boolean isContinuation()
|
||||
{
|
||||
return continuation;
|
||||
}
|
||||
|
||||
public void setContinuation(boolean continuation)
|
||||
{
|
||||
this.continuation = continuation;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
/**
|
||||
|
@ -7,8 +9,6 @@ import org.eclipse.jetty.websocket.api.OpCode;
|
|||
*/
|
||||
public class TextFrame extends DataFrame
|
||||
{
|
||||
private StringBuilder data = new StringBuilder();
|
||||
|
||||
/**
|
||||
* Default constructor (unspecified data)
|
||||
*/
|
||||
|
@ -26,17 +26,7 @@ public class TextFrame extends DataFrame
|
|||
public TextFrame(String message)
|
||||
{
|
||||
this();
|
||||
setData(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data
|
||||
*
|
||||
* @return the raw StringBuilder data (can be null)
|
||||
*/
|
||||
public StringBuilder getData()
|
||||
{
|
||||
return data;
|
||||
setPayload(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,24 +35,18 @@ public class TextFrame extends DataFrame
|
|||
* @param str
|
||||
* the String to set
|
||||
*/
|
||||
public void setData(String str)
|
||||
public void setPayload(String str)
|
||||
{
|
||||
int len = str.length();
|
||||
this.data = new StringBuilder(str);
|
||||
ByteBuffer b = ByteBuffer.allocate(len);
|
||||
b.put(str.getBytes()); // TODO validate utf-8
|
||||
this.setPayload(b);
|
||||
this.setPayloadLength(len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data and payload length.
|
||||
*
|
||||
* @param str
|
||||
* the StringBuilder to set
|
||||
*/
|
||||
public void setData(StringBuilder str)
|
||||
public String getPayloadAsText()
|
||||
{
|
||||
int len = str.length();
|
||||
this.data = str;
|
||||
this.setPayloadLength(len);
|
||||
return new String(getPayload().array());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +55,7 @@ public class TextFrame extends DataFrame
|
|||
StringBuilder b = new StringBuilder();
|
||||
b.append("TextFrame[");
|
||||
b.append("len=").append(getPayloadLength());
|
||||
b.append(",data=").append(data);
|
||||
b.append(",data=").append(getPayload()); // TODO pp
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ public class BinaryFrameGenerator extends FrameGenerator<BinaryFrame>
|
|||
@Override
|
||||
public ByteBuffer payload(BinaryFrame binary)
|
||||
{
|
||||
return binary.getData();
|
||||
return binary.getPayload();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package org.eclipse.jetty.websocket.generator;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
import org.eclipse.jetty.websocket.api.PolicyViolationException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.DataFrame;
|
||||
|
||||
public abstract class FrameGenerator<T extends BaseFrame>
|
||||
{
|
||||
|
@ -48,7 +50,24 @@ public abstract class FrameGenerator<T extends BaseFrame>
|
|||
// TODO: extensions can negotiate this (somehow)
|
||||
throw new PolicyViolationException("RSV3 not allowed to be set");
|
||||
}
|
||||
|
||||
// TODO ewe
|
||||
if ( frame instanceof DataFrame)
|
||||
{
|
||||
if ( ((DataFrame)frame).isContinuation() )
|
||||
{
|
||||
b |= OpCode.CONTINUATION.getCode() & 0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
b |= (frame.getOpCode().getCode() & 0x0F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b |= (frame.getOpCode().getCode() & 0x0F);
|
||||
}
|
||||
|
||||
framing.put(b);
|
||||
|
||||
// is masked
|
||||
|
|
|
@ -18,18 +18,6 @@ public class TextFrameGenerator extends FrameGenerator<TextFrame>
|
|||
@Override
|
||||
public ByteBuffer payload(TextFrame text)
|
||||
{
|
||||
try
|
||||
{
|
||||
String data = text.getData().toString();
|
||||
ByteBuffer payload = ByteBuffer.allocate(data.length());
|
||||
payload.put(data.getBytes("UTF-8"));
|
||||
return payload;
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
// TODO improve ex handling
|
||||
throw new WebSocketException("text frame was not correctly encoded");
|
||||
}
|
||||
|
||||
return text.getPayload();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class BinaryPayloadParser extends FrameParser<BinaryFrame>
|
|||
|
||||
if (payload.position() >= payloadLength)
|
||||
{
|
||||
frame.setData(payload);
|
||||
frame.setPayload(payload);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.eclipse.jetty.websocket.api.OpCode;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.DataFrame;
|
||||
|
||||
/**
|
||||
* Parsing of a frames in WebSocket land.
|
||||
|
@ -139,7 +140,11 @@ public class Parser
|
|||
}
|
||||
parser.reset();
|
||||
parser.initFrame(fin,rsv1,rsv2,rsv3,opcode);
|
||||
parser.getFrame().setContinuationIndex(currentContinuationIndex);
|
||||
|
||||
if ( parser.getFrame() instanceof DataFrame )
|
||||
{
|
||||
((DataFrame)parser.getFrame()).setContinuationIndex(currentContinuationIndex);
|
||||
}
|
||||
|
||||
state = State.BASE_FRAMING;
|
||||
break;
|
||||
|
|
|
@ -49,7 +49,7 @@ public class TextPayloadParser extends FrameParser<TextFrame>
|
|||
if (payload.position() >= payloadLength)
|
||||
{
|
||||
payload.flip();
|
||||
frame.setData(BufferUtil.toString(payload,StringUtil.__UTF8_CHARSET));
|
||||
frame.setPayload(BufferUtil.toString(payload,StringUtil.__UTF8_CHARSET));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class GeneratorParserRoundtripTest
|
|||
capture.assertHasFrame(TextFrame.class,1);
|
||||
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("Text parsed",txt.getData().toString(),is(message));
|
||||
Assert.assertThat("Text parsed",txt.getPayloadAsText(),is(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -82,6 +82,6 @@ public class GeneratorParserRoundtripTest
|
|||
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertTrue("Text.isMasked",txt.isMasked());
|
||||
Assert.assertThat("Text parsed",txt.getData().toString(),is(message));
|
||||
Assert.assertThat("Text parsed",txt.getPayloadAsText(),is(message));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,9 @@ public class RFC6455ExamplesGeneratorTest
|
|||
|
||||
t1.setFin(false);
|
||||
t2.setFin(true);
|
||||
t1.setData("Hel");
|
||||
t2.setData("lo");
|
||||
t2.setContinuation(true);
|
||||
t1.setPayload("Hel");
|
||||
t2.setPayload("lo");
|
||||
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
|
||||
|
@ -58,11 +59,6 @@ public class RFC6455ExamplesGeneratorTest
|
|||
b2.flip();
|
||||
g2.flip();
|
||||
|
||||
Assert.assertEquals(b1.get(),g1.get());
|
||||
|
||||
System.out.println(Integer.toHexString(b2.get()));
|
||||
System.out.println(Integer.toHexString(g2.get()));
|
||||
|
||||
ByteBufferAssert.assertEquals("t1 buffers are not equal", b1, g1);
|
||||
ByteBufferAssert.assertEquals("t2 buffers are not equal", b2, g2);
|
||||
|
||||
|
@ -149,7 +145,7 @@ public class RFC6455ExamplesGeneratorTest
|
|||
{ (byte)0x81, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 });
|
||||
|
||||
TextFrame t1 = new TextFrame();
|
||||
t1.setData("Hello");
|
||||
t1.setPayload("Hello");
|
||||
t1.setFin(true);
|
||||
t1.setMasked(true);
|
||||
t1.setMask(new byte[]{(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff});
|
||||
|
|
|
@ -51,9 +51,9 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertHasFrame(TextFrame.class,2);
|
||||
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame[0].data",txt.getData().toString(),is("Hel"));
|
||||
Assert.assertThat("TextFrame[0].data",txt.getPayloadAsText(),is("Hel"));
|
||||
txt = (TextFrame)capture.getFrames().get(1);
|
||||
Assert.assertThat("TextFrame[1].data",txt.getData().toString(),is("lo"));
|
||||
Assert.assertThat("TextFrame[1].data",txt.getPayloadAsText(),is("lo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -99,7 +99,7 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertHasFrame(TextFrame.class,1);
|
||||
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data",txt.getData().toString(),is("Hello"));
|
||||
Assert.assertThat("TextFrame.data",txt.getPayloadAsText(),is("Hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -129,12 +129,12 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertHasFrame(BinaryFrame.class,1);
|
||||
|
||||
BinaryFrame bin = (BinaryFrame)capture.getFrames().get(0);
|
||||
bin.getData().flip();
|
||||
bin.getPayload().flip();
|
||||
|
||||
Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize));
|
||||
ByteBufferAssert.assertSize("BinaryFrame.payload",dataSize,bin.getData());
|
||||
ByteBufferAssert.assertSize("BinaryFrame.payload",dataSize,bin.getPayload());
|
||||
|
||||
ByteBuffer data = bin.getData();
|
||||
ByteBuffer data = bin.getPayload();
|
||||
for (int i = dataSize; i > 0; i--)
|
||||
{
|
||||
Assert.assertThat("BinaryFrame.data[" + i + "]",data.get(),is((byte)0x44));
|
||||
|
@ -168,12 +168,12 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertHasFrame(BinaryFrame.class,1);
|
||||
|
||||
BinaryFrame bin = (BinaryFrame)capture.getFrames().get(0);
|
||||
bin.getData().flip();
|
||||
bin.getPayload().flip();
|
||||
|
||||
Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize));
|
||||
ByteBufferAssert.assertSize("BinaryFrame.payload",dataSize,bin.getData());
|
||||
ByteBufferAssert.assertSize("BinaryFrame.payload",dataSize,bin.getPayload());
|
||||
|
||||
ByteBuffer data = bin.getData();
|
||||
ByteBuffer data = bin.getPayload();
|
||||
for (int i = dataSize; i > 0; i--)
|
||||
{
|
||||
Assert.assertThat("BinaryFrame.data[" + i + "]",data.get(),is((byte)0x77));
|
||||
|
@ -223,6 +223,6 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertHasFrame(TextFrame.class,1);
|
||||
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data", txt.getData().toString(), is("Hello"));
|
||||
Assert.assertThat("TextFrame.data", txt.getPayloadAsText(), is("Hello"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class TextPayloadParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(TextFrame.class,1);
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data",txt.getData().toString(),is(expectedText));
|
||||
Assert.assertThat("TextFrame.data",txt.getPayloadAsText(),is(expectedText));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -113,7 +113,7 @@ public class TextPayloadParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(TextFrame.class,1);
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data",txt.getData().toString(),is(expectedText));
|
||||
Assert.assertThat("TextFrame.data",txt.getPayloadAsText(),is(expectedText));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -150,9 +150,9 @@ public class TextPayloadParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(TextFrame.class,2);
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame[0].data",txt.getData().toString(),is(part1));
|
||||
Assert.assertThat("TextFrame[0].data",txt.getPayloadAsText(),is(part1));
|
||||
txt = (TextFrame)capture.getFrames().get(1);
|
||||
Assert.assertThat("TextFrame[1].data",txt.getData().toString(),is(part2));
|
||||
Assert.assertThat("TextFrame[1].data",txt.getPayloadAsText(),is(part2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -177,7 +177,7 @@ public class TextPayloadParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(TextFrame.class,1);
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data",txt.getData().toString(),is(expectedText));
|
||||
Assert.assertThat("TextFrame.data",txt.getPayloadAsText(),is(expectedText));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -203,6 +203,6 @@ public class TextPayloadParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(TextFrame.class,1);
|
||||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data",txt.getData().toString(),is(expectedText));
|
||||
Assert.assertThat("TextFrame.data",txt.getPayloadAsText(),is(expectedText));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue