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 index 76d24542c13..dad21e71ab0 100644 --- 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 @@ -94,7 +94,7 @@ public abstract class FrameGenerator { b |= 0x7E; framing.put(b); // indicate 2 byte length - framing.put((byte)((payloadLength>>8) & 0xFF)); + framing.put((byte)(payloadLength>>8)); framing.put((byte)(payloadLength & 0xFF)); } /* diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java index b9a0b260678..14e00d278c9 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java @@ -145,12 +145,14 @@ public abstract class FrameParser getFrame().setMasked((b & 0x80) != 0); length = (byte)(0x7F & b); + System.out.println(length); if (length == 127) { - // length 4 bytes (extended payload length) + // length 8 bytes (extended payload length) if (buffer.remaining() >= 4) { - length = buffer.getInt(); + buffer.getInt(); //toss the first one, first 4 bytes + length = buffer.getInt(); // last 4 bytes for actual length } else { @@ -166,6 +168,10 @@ public abstract class FrameParser if (buffer.remaining() >= 2) { length = buffer.getShort(); + if (length == -1) + { + length = 65535; + } } else { diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1.java index 243cd8dcf08..6d71a59e6a7 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1.java @@ -7,6 +7,7 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.io.StandardByteBufferPool; 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; @@ -14,6 +15,7 @@ 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; @@ -217,4 +219,314 @@ public class ABCase1 Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); } + + @Test + public void testGenerate127ByteTextCase1_1_4() + { + int length = 127; + + StringBuilder builder = new StringBuilder(); + + for ( int i = 0 ; i < length ; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + 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)0x81 }); + + 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 testParse127ByteTextCase1_1_4() + { + int length = 127; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + 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(TextFrame.class,1); + + TextFrame pActual = (TextFrame)capture.getFrames().get(0); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + } + + @Test + public void testGenerate128ByteTextCase1_1_5() + { + int length = 128; + + StringBuilder builder = new StringBuilder(); + + for ( int i = 0 ; i < length ; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + 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)0x81 }); + + 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 testParse128ByteTextCase1_1_5() + { + int length = 128; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + 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(TextFrame.class,1); + + TextFrame pActual = (TextFrame)capture.getFrames().get(0); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + } + + @Test + public void testGenerate65535ByteTextCase1_1_6() + { + int length = 65535; + + StringBuilder builder = new StringBuilder(); + + for ( int i = 0 ; i < length ; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + 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)0x81 }); + + 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 testParse65535ByteTextCase1_1_6() + { + Debug.enableDebugLogging(Parser.class); + Debug.enableDebugLogging(TextPayloadParser.class); + + int length = 65535; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + 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(TextFrame.class,1); + + TextFrame pActual = (TextFrame)capture.getFrames().get(0); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + } + + + @Test + public void testGenerate65536ByteTextCase1_1_7() + { + int length = 65536; + + StringBuilder builder = new StringBuilder(); + + for ( int i = 0 ; i < length ; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + 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)0x81 }); + + 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 testParse65536ByteTextCase1_1_7() + { + int length = 65536; + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x81 }); + 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(TextFrame.class,1); + + TextFrame pActual = (TextFrame)capture.getFrames().get(0); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + } } diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/generator/RFC6455ExamplesGeneratorTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/generator/RFC6455ExamplesGeneratorTest.java index 7a238f21839..4b045d2f225 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/generator/RFC6455ExamplesGeneratorTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/generator/RFC6455ExamplesGeneratorTest.java @@ -235,7 +235,8 @@ public class RFC6455ExamplesGeneratorTest // 64k bytes binary message in a single unmasked frame expected.put(new byte[] { (byte)0x82, (byte)0x7F }); - expected.putInt(0x0000000000010000); + expected.putInt(0x00_00_00_00); + expected.putInt(0x00_01_00_00); for (int i = 0; i < dataSize; i++) {