Reworking Generator (with jesse on a hangout)

This commit is contained in:
Joakim Erdfelt 2012-06-19 14:05:47 -07:00
parent 228565068f
commit 30901917eb
7 changed files with 101 additions and 83 deletions

View File

@ -3,29 +3,18 @@ package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.api.OpCode;
import org.eclipse.jetty.websocket.frames.CloseFrame; import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.ControlFrame;
public class CloseFrameGenerator extends ControlFrameGenerator public class CloseFrameGenerator extends FrameGenerator<CloseFrame>
{ {
public CloseFrameGenerator(ByteBufferPool bufferPool) public CloseFrameGenerator(ByteBufferPool bufferPool)
{ {
super(bufferPool); super(bufferPool);
} }
@Override @Override
public ByteBuffer generate(ControlFrame frame) public void generatePayload(ByteBuffer buffer, CloseFrame close)
{ {
CloseFrame close = (CloseFrame)frame;
ByteBuffer buffer = super.generate(frame);
buffer.putInt(OpCode.CLOSE.getCode());
buffer.put(frame.getMask());
buffer.putLong(frame.getPayloadLength());
buffer.put(close.getReason().getBytes()); buffer.put(close.getReason().getBytes());
return buffer;
} }
} }

View File

@ -1,39 +0,0 @@
package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.frames.ControlFrame;
public abstract class ControlFrameGenerator
{
private final ByteBufferPool bufferPool;
protected ControlFrameGenerator(ByteBufferPool bufferPool)
{
this.bufferPool = bufferPool;
}
public ByteBuffer generate(ControlFrame frame)
{
// how to calculate the size since control frames may hold
// application data
// grabing 125 now since that is _max_ possible
ByteBuffer buffer = getByteBufferPool().acquire(125,true);
// all control frames are FIN as they can not be fragmented
buffer.putInt(0x80);
// revisit this on extensions since they can negotiate this
buffer.putInt(0);
buffer.putInt(0);
buffer.putInt(0);
return buffer;
}
protected ByteBufferPool getByteBufferPool()
{
return bufferPool;
}
}

View File

@ -0,0 +1,85 @@
package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.frames.BaseFrame;
public abstract class FrameGenerator<T extends BaseFrame>
{
private final ByteBufferPool bufferPool;
protected FrameGenerator(ByteBufferPool bufferPool)
{
this.bufferPool = bufferPool;
}
public ByteBuffer generate(T frame)
{
ByteBuffer framing = ByteBuffer.allocate(16);
byte b;
// Setup fin thru opcode
b = 0x00;
b |= (frame.isFin()?0x80:0x00); // 1000_0000
b |= (frame.isRsv1()?0x40:0x00); // 0100_0000
b |= (frame.isRsv2()?0x20:0x00); // 0010_0000 TODO: validate?
b |= (frame.isRsv3()?0x10:0x00); // 0001_0000 TODO: validate?
b |= (frame.getOpCode().getCode() & 0x0F);
framing.put(b);
// is masked
b = 0x00;
b |= (frame.isMasked()?0x80:0x00);
// payload lengths
int payloadLength = frame.getPayloadLength();
if (payloadLength >= 0x7F)
{
// we have a 64 bit length
b |= 0x7F;
framing.put(b);
framing.putInt(payloadLength);
}
else if (payloadLength >= 0x7E)
{
// we have a 16 bit length
b |= 0x7E;
framing.put(b);
framing.putShort((short)(payloadLength & 0xFFFF));
}
else
{
// we have a 7 bit length
b |= (payloadLength & 0x7F);
framing.put(b);
}
// masking key
if (frame.isMasked())
{
// TODO: figure out maskgen
framing.put(frame.getMask());
}
framing.flip(); // to figure out how many bytes are used
// now the payload itself
int buflen = frame.getPayloadLength() + framing.remaining();
ByteBuffer buffer = ByteBuffer.allocate(buflen);
// TODO: figure out how to get this from a bytebuffer pool
generatePayload(buffer, frame);
return buffer;
}
public abstract void generatePayload(ByteBuffer buffer, T frame);
protected ByteBufferPool getByteBufferPool()
{
return bufferPool;
}
}

View File

@ -5,7 +5,7 @@ import java.util.EnumMap;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.api.OpCode; import org.eclipse.jetty.websocket.api.OpCode;
import org.eclipse.jetty.websocket.frames.ControlFrame; import org.eclipse.jetty.websocket.frames.BaseFrame;
/** /**
* Generating a frame in WebSocket land. * Generating a frame in WebSocket land.
@ -33,24 +33,21 @@ import org.eclipse.jetty.websocket.frames.ControlFrame;
*/ */
public class Generator { public class Generator {
private final EnumMap<OpCode, ControlFrameGenerator> generators = new EnumMap<>(OpCode.class); private final EnumMap<OpCode, FrameGenerator<?>> generators = new EnumMap<>(OpCode.class);
public Generator(ByteBufferPool bufferPool) //, CompressionFactory.Compressor compressor) public Generator(ByteBufferPool bufferPool) //, CompressionFactory.Compressor compressor)
{ {
HeadersBlockGenerator headerBlockGenerator = new HeadersBlockGenerator();
generators.put(OpCode.PING,new PingFrameGenerator(bufferPool)); generators.put(OpCode.PING,new PingFrameGenerator(bufferPool));
generators.put(OpCode.PONG,new PongFrameGenerator(bufferPool)); generators.put(OpCode.PONG,new PongFrameGenerator(bufferPool));
generators.put(OpCode.CLOSE,new CloseFrameGenerator(bufferPool)); generators.put(OpCode.CLOSE,new CloseFrameGenerator(bufferPool));
} }
@SuppressWarnings(
public ByteBuffer control(ControlFrame frame) { "unchecked", "rawtypes" })
public ByteBuffer control(BaseFrame frame)
{ {
ControlFrameGenerator generator = generators.get(frame.getOpCode()); FrameGenerator generator = generators.get(frame.getOpCode());
return generator.generate(frame); return generator.generate(frame);
} }
} }

View File

@ -3,11 +3,9 @@ package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.api.OpCode;
import org.eclipse.jetty.websocket.frames.ControlFrame;
import org.eclipse.jetty.websocket.frames.PingFrame; import org.eclipse.jetty.websocket.frames.PingFrame;
public class PingFrameGenerator extends ControlFrameGenerator public class PingFrameGenerator extends FrameGenerator<PingFrame>
{ {
public PingFrameGenerator(ByteBufferPool bufferPool) public PingFrameGenerator(ByteBufferPool bufferPool)
{ {
@ -15,18 +13,8 @@ public class PingFrameGenerator extends ControlFrameGenerator
} }
@Override @Override
public ByteBuffer generate(ControlFrame frame) public void generatePayload(ByteBuffer buffer, PingFrame ping)
{ {
PingFrame ping = (PingFrame)frame;
ByteBuffer buffer = super.generate(frame);
buffer.putInt(OpCode.PING.getCode());
buffer.put(frame.getMask());
buffer.putLong(frame.getPayloadLength());
buffer.put(ping.getPayload().array()); buffer.put(ping.getPayload().array());
return buffer;
} }
} }

View File

@ -3,20 +3,18 @@ package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.frames.ControlFrame; import org.eclipse.jetty.websocket.frames.PongFrame;
public class PongFrameGenerator extends ControlFrameGenerator public class PongFrameGenerator extends FrameGenerator<PongFrame>
{ {
public PongFrameGenerator(ByteBufferPool bufferPool) public PongFrameGenerator(ByteBufferPool bufferPool)
{ {
super(bufferPool); super(bufferPool);
} }
@Override @Override
public ByteBuffer generate(ControlFrame frame) public void generatePayload(ByteBuffer buffer, PongFrame frame)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null;
} }
} }

View File

@ -13,7 +13,7 @@ public class PingParserTest
{ {
Debug.enableDebugLogging(Parser.class); Debug.enableDebugLogging(Parser.class);
ByteBuffer buf = ByteBuffer.allocate(7); ByteBuffer buf = ByteBuffer.allocate(16);
buf.put(new byte[] buf.put(new byte[]
{ (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); { (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
Debug.dumpState(buf); Debug.dumpState(buf);