From 30901917ebdfc782bbf3301f35089b517f0381be Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 19 Jun 2012 14:05:47 -0700 Subject: [PATCH] Reworking Generator (with jesse on a hangout) --- .../generator/CloseFrameGenerator.java | 17 +--- .../generator/ControlFrameGenerator.java | 39 --------- .../websocket/generator/FrameGenerator.java | 85 +++++++++++++++++++ .../jetty/websocket/generator/Generator.java | 15 ++-- .../generator/PingFrameGenerator.java | 16 +--- .../generator/PongFrameGenerator.java | 10 +-- .../websocket/parser/PingParserTest.java | 2 +- 7 files changed, 101 insertions(+), 83 deletions(-) delete mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/ControlFrameGenerator.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/FrameGenerator.java diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/CloseFrameGenerator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/CloseFrameGenerator.java index 92bd15ff608..c6fbd048fa4 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/CloseFrameGenerator.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/CloseFrameGenerator.java @@ -3,29 +3,18 @@ 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.frames.CloseFrame; -import org.eclipse.jetty.websocket.frames.ControlFrame; -public class CloseFrameGenerator extends ControlFrameGenerator +public class CloseFrameGenerator extends FrameGenerator { public CloseFrameGenerator(ByteBufferPool bufferPool) { super(bufferPool); } + @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()); - - return buffer; } - } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/ControlFrameGenerator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/ControlFrameGenerator.java deleted file mode 100644 index 7ae5f164a0d..00000000000 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/ControlFrameGenerator.java +++ /dev/null @@ -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; - } -} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/FrameGenerator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/FrameGenerator.java new file mode 100644 index 00000000000..1d02369a11e --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/FrameGenerator.java @@ -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 +{ + 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; + } +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/Generator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/Generator.java index c779b908862..c90b5477023 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/Generator.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/Generator.java @@ -5,7 +5,7 @@ import java.util.EnumMap; 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.BaseFrame; /** * Generating a frame in WebSocket land. @@ -33,24 +33,21 @@ import org.eclipse.jetty.websocket.frames.ControlFrame; */ public class Generator { - private final EnumMap generators = new EnumMap<>(OpCode.class); + private final EnumMap> generators = new EnumMap<>(OpCode.class); public Generator(ByteBufferPool bufferPool) //, CompressionFactory.Compressor compressor) { - HeadersBlockGenerator headerBlockGenerator = new HeadersBlockGenerator(); generators.put(OpCode.PING,new PingFrameGenerator(bufferPool)); generators.put(OpCode.PONG,new PongFrameGenerator(bufferPool)); generators.put(OpCode.CLOSE,new CloseFrameGenerator(bufferPool)); - } - - public ByteBuffer control(ControlFrame frame) + @SuppressWarnings( + { "unchecked", "rawtypes" }) + public ByteBuffer control(BaseFrame frame) { - ControlFrameGenerator generator = generators.get(frame.getOpCode()); + FrameGenerator generator = generators.get(frame.getOpCode()); return generator.generate(frame); } - - } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PingFrameGenerator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PingFrameGenerator.java index 669a0b404a2..1d9df08d680 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PingFrameGenerator.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PingFrameGenerator.java @@ -3,11 +3,9 @@ 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.frames.ControlFrame; import org.eclipse.jetty.websocket.frames.PingFrame; -public class PingFrameGenerator extends ControlFrameGenerator +public class PingFrameGenerator extends FrameGenerator { public PingFrameGenerator(ByteBufferPool bufferPool) { @@ -15,18 +13,8 @@ public class PingFrameGenerator extends ControlFrameGenerator } @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()); - return buffer; } - } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PongFrameGenerator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PongFrameGenerator.java index c38a91902c8..159095f38e0 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PongFrameGenerator.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/generator/PongFrameGenerator.java @@ -3,20 +3,18 @@ package org.eclipse.jetty.websocket.generator; import java.nio.ByteBuffer; 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 { public PongFrameGenerator(ByteBufferPool bufferPool) { super(bufferPool); } - + @Override - public ByteBuffer generate(ControlFrame frame) + public void generatePayload(ByteBuffer buffer, PongFrame frame) { // TODO Auto-generated method stub - return null; } - } diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/PingParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/PingParserTest.java index bb55ae81bb4..4aca12c9e3a 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/PingParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/PingParserTest.java @@ -13,7 +13,7 @@ public class PingParserTest { Debug.enableDebugLogging(Parser.class); - ByteBuffer buf = ByteBuffer.allocate(7); + ByteBuffer buf = ByteBuffer.allocate(16); buf.put(new byte[] { (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); Debug.dumpState(buf);