From b37da5a5daa01db558eda9031f645a1d0e941e75 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 9 Aug 2012 13:17:07 -0700 Subject: [PATCH] Making payload fast-fail and demasking work together in peace and harmony --- .../websocket/io/payload/BinaryValidator.java | 25 +++++ .../io/payload/CloseReasonValidator.java | 32 +++++++ .../websocket/io/payload/DeMaskProcessor.java | 44 +++++++++ .../io/payload/PayloadProcessor.java | 24 +++++ .../websocket/io/payload/UTF8Validator.java | 93 +++++++++++++++++++ .../jetty/websocket/protocol/Parser.java | 60 ++++++++---- .../jetty/websocket/ByteBufferAssert.java | 4 +- .../io/payload/DeMaskProcessorTest.java | 39 ++++++++ .../io/payload/UTF8ValidatorTest.java | 38 ++++++++ .../jetty/websocket/protocol/ParserTest.java | 56 ++++++++++- .../test/resources/jetty-logging.properties | 4 +- .../websocket/server/ab/TestABCase6.java | 34 +++++-- .../test/resources/jetty-logging.properties | 1 + 13 files changed, 426 insertions(+), 28 deletions(-) create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/BinaryValidator.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/CloseReasonValidator.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessor.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/PayloadProcessor.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/UTF8Validator.java create mode 100644 jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessorTest.java create mode 100644 jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/UTF8ValidatorTest.java diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/BinaryValidator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/BinaryValidator.java new file mode 100644 index 00000000000..1b88008f6d0 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/BinaryValidator.java @@ -0,0 +1,25 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; + +/** + * Binary payload validator does nothing, essentially. + */ +public class BinaryValidator implements PayloadProcessor +{ + public static final BinaryValidator INSTANCE = new BinaryValidator(); + + @Override + public void process(ByteBuffer payload) + { + /* all payloads are valid in this case */ + } + + @Override + public void reset(WebSocketFrame frame) + { + /* do nothing */ + } +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/CloseReasonValidator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/CloseReasonValidator.java new file mode 100644 index 00000000000..3d11eb9c024 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/CloseReasonValidator.java @@ -0,0 +1,32 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.protocol.OpCode; + +/** + * Validate UTF8 correctness for {@link OpCode#CLOSE} Reason message. + */ +public class CloseReasonValidator extends UTF8Validator implements PayloadProcessor +{ + private int statusCodeBytes = 2; + + @Override + public void process(ByteBuffer payload) + { + if ((payload == null) || (payload.remaining() <= 2)) + { + // no validation needed + return; + } + + ByteBuffer copy = payload.slice(); + while (statusCodeBytes > 0) + { + copy.get(); + statusCodeBytes--; + } + + super.process(copy); + } +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessor.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessor.java new file mode 100644 index 00000000000..2582982cadd --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessor.java @@ -0,0 +1,44 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; + +public class DeMaskProcessor implements PayloadProcessor +{ + private boolean isMasked; + private byte mask[]; + private int offset; + + @Override + public void process(ByteBuffer payload) + { + if (!isMasked) + { + return; + } + + int start = payload.position(); + int end = payload.limit(); + for (int i = start; i < end; i++, offset++) + { + payload.put(i,(byte)(payload.get(i) ^ mask[offset % 4])); + } + } + + @Override + public void reset(WebSocketFrame frame) + { + this.isMasked = frame.isMasked(); + if (isMasked) + { + this.mask = frame.getMask(); + } + else + { + this.mask = null; + } + + offset = 0; + } +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/PayloadProcessor.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/PayloadProcessor.java new file mode 100644 index 00000000000..6cb9816b33a --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/PayloadProcessor.java @@ -0,0 +1,24 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.api.BadPayloadException; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; + +/** + * Process the payload (for demasking, validating, etc..) + */ +public interface PayloadProcessor +{ + /** + * Used to process payloads for in the spec. + * + * @param payload + * the payload to process + * @throws BadPayloadException + * the exception when the payload fails to validate properly + */ + public void process(ByteBuffer payload); + + public void reset(WebSocketFrame frame); +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/UTF8Validator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/UTF8Validator.java new file mode 100644 index 00000000000..c6ac203ba29 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/payload/UTF8Validator.java @@ -0,0 +1,93 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.Utf8Appendable; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.BadPayloadException; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; + +/** + * Used to perform validation of UTF8 payload contents (for fast-fail reasons) + */ +public class UTF8Validator extends Utf8Appendable implements PayloadProcessor +{ + private static class EmptyAppender implements Appendable + { + private int length = 0; + + @Override + public Appendable append(char c) throws IOException + { + length++; + return this; + } + + @Override + public Appendable append(CharSequence csq) throws IOException + { + length += csq.length(); + return this; + } + + @Override + public Appendable append(CharSequence csq, int start, int end) throws IOException + { + length += (end - start); + return this; + } + + public int getLength() + { + return length; + } + } + + private static final Logger LOG = Log.getLogger(UTF8Validator.class); + + private EmptyAppender buffer; + + public UTF8Validator() + { + super(new EmptyAppender()); + this.buffer = (EmptyAppender)_appendable; + } + + @Override + public int length() + { + return this.buffer.getLength(); + } + + @Override + public void process(ByteBuffer payload) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("Payload: {}",BufferUtil.toDetailString(payload)); + } + + if ((payload == null) || (payload.remaining() <= 0)) + { + return; + } + + try + { + append(payload.slice()); + } + catch (NotUtf8Exception e) + { + throw new BadPayloadException(e); + } + } + + @Override + public void reset(WebSocketFrame frame) + { + /* do nothing */ + } +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java index eead9e91541..5e8117f3d62 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java @@ -25,6 +25,11 @@ import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.io.IncomingFrames; +import org.eclipse.jetty.websocket.io.payload.BinaryValidator; +import org.eclipse.jetty.websocket.io.payload.CloseReasonValidator; +import org.eclipse.jetty.websocket.io.payload.DeMaskProcessor; +import org.eclipse.jetty.websocket.io.payload.PayloadProcessor; +import org.eclipse.jetty.websocket.io.payload.UTF8Validator; /** * Parsing of a frames in WebSocket land. @@ -54,6 +59,8 @@ public class Parser // payload specific private ByteBuffer payload; private int payloadLength; + private PayloadProcessor maskProcessor = new DeMaskProcessor(); + private PayloadProcessor strictnessProcessor; /** Is there an extension using RSV1 */ private boolean rsv1InUse = false; @@ -277,6 +284,19 @@ public class Parser boolean isContinuation = false; + switch (opcode) + { + case OpCode.TEXT: + strictnessProcessor = new UTF8Validator(); + break; + case OpCode.CLOSE: + strictnessProcessor = new CloseReasonValidator(); + break; + default: + strictnessProcessor = BinaryValidator.INSTANCE; + break; + } + if (OpCode.isControlFrame(opcode)) { // control frame validation @@ -359,6 +379,7 @@ public class Parser return true; } + maskProcessor.reset(frame); state = State.PAYLOAD; } @@ -385,6 +406,7 @@ public class Parser return true; } + maskProcessor.reset(frame); state = State.PAYLOAD; } } @@ -404,6 +426,7 @@ public class Parser return true; } + maskProcessor.reset(frame); state = State.PAYLOAD; } else @@ -427,6 +450,7 @@ public class Parser return true; } + maskProcessor.reset(frame); state = State.PAYLOAD; } break; @@ -476,27 +500,29 @@ public class Parser BufferUtil.clearToFill(payload); } - BufferUtil.put(buffer,payload); + // Create a small window of the incoming buffer to work with. + // this should only show the payload itself, and not any more + // bytes that could belong to the start of the next frame. + ByteBuffer window = buffer.slice(); + int bytesExpected = payloadLength - payload.position(); + int bytesAvailable = buffer.remaining(); + int windowBytes = Math.min(bytesAvailable,bytesExpected); + window.limit(window.position() + windowBytes); + + if (LOG.isDebugEnabled()) + { + LOG.debug("Window: {}",BufferUtil.toDetailString(window)); + } + + maskProcessor.process(window); + strictnessProcessor.process(window); + int len = BufferUtil.put(window,payload); + + buffer.position(buffer.position() + len); // update incoming buffer position if (payload.position() >= payloadLength) { BufferUtil.flipToFlush(payload,0); - - LOG.debug("PreMask: {}",BufferUtil.toDetailString(payload)); - // demask (if needed) - if (frame.isMasked()) - { - byte mask[] = frame.getMask(); - int offset; - int start = payload.position(); - int end = payload.limit(); - for (int i = start; i < end; i++) - { - offset = (i - start); - payload.put(i,(byte)(payload.get(i) ^ mask[offset % 4])); - } - } - frame.setPayload(payload); this.payload = null; return true; diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ByteBufferAssert.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ByteBufferAssert.java index 11d99194477..32948a1982a 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ByteBufferAssert.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ByteBufferAssert.java @@ -15,7 +15,7 @@ //======================================================================== package org.eclipse.jetty.websocket; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; import java.nio.ByteBuffer; @@ -44,7 +44,7 @@ public class ByteBufferAssert public static void assertEquals(String message, String expectedString, ByteBuffer actualBuffer) { String actualString = BufferUtil.toString(actualBuffer); - Assert.assertThat(message,expectedString,is(actualString)); + Assert.assertThat(message,actualString,is(expectedString)); } public static void assertSize(String message, int expectedSize, ByteBuffer buffer) diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessorTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessorTest.java new file mode 100644 index 00000000000..e012d2180da --- /dev/null +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/DeMaskProcessorTest.java @@ -0,0 +1,39 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.TypeUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.ByteBufferAssert; +import org.eclipse.jetty.websocket.protocol.UnitGenerator; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; +import org.junit.Test; + +public class DeMaskProcessorTest +{ + private static final Logger LOG = Log.getLogger(DeMaskProcessorTest.class); + + @Test + public void testDeMaskText() + { + String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; + + WebSocketFrame frame = WebSocketFrame.text(message); + frame.setMask(TypeUtil.fromHexString("11223344")); + // frame.setMask(TypeUtil.fromHexString("00000000")); + + ByteBuffer buf = new UnitGenerator().generate(frame); + LOG.debug("Buf: {}",BufferUtil.toDetailString(buf)); + ByteBuffer payload = buf.slice(); + payload.position(6); // where payload starts + LOG.debug("Payload: {}",BufferUtil.toDetailString(payload)); + + DeMaskProcessor demask = new DeMaskProcessor(); + demask.reset(frame); + demask.process(payload); + + ByteBufferAssert.assertEquals("DeMasked Text Payload",message,payload); + } +} diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/UTF8ValidatorTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/UTF8ValidatorTest.java new file mode 100644 index 00000000000..78c478ee10f --- /dev/null +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/io/payload/UTF8ValidatorTest.java @@ -0,0 +1,38 @@ +package org.eclipse.jetty.websocket.io.payload; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.TypeUtil; +import org.eclipse.jetty.websocket.api.BadPayloadException; +import org.junit.Assert; +import org.junit.Test; + +public class UTF8ValidatorTest +{ + private ByteBuffer asByteBuffer(String hexStr) + { + byte buf[] = TypeUtil.fromHexString(hexStr); + return ByteBuffer.wrap(buf); + } + + @Test + public void testCase6_4_3() + { + ByteBuffer part1 = asByteBuffer("cebae1bdb9cf83cebcceb5"); // good + ByteBuffer part2 = asByteBuffer("f4908080"); // INVALID + ByteBuffer part3 = asByteBuffer("656469746564"); // good + + UTF8Validator validator = new UTF8Validator(); + validator.process(part1); // good + try + { + validator.process(part2); // bad + Assert.fail("Expected a " + BadPayloadException.class); + } + catch (BadPayloadException e) + { + // expected path + } + validator.process(part3); // good + } +} diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java index ab3a76b106e..8d6ce199f4c 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java @@ -15,13 +15,18 @@ //======================================================================== package org.eclipse.jetty.websocket.protocol; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.TypeUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.BadPayloadException; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; @@ -30,6 +35,8 @@ import org.junit.Test; public class ParserTest { + private static final Logger LOG = Log.getLogger(ParserTest.class); + /** * Similar to the server side 5.15 testcase. A normal 2 fragment text text message, followed by another continuation. */ @@ -163,6 +170,53 @@ public class ParserTest capture.assertHasFrame(OpCode.CLOSE,1); } + /** + * Similar to the server side 6.4.3 testcase. + */ + @Test + public void testParseCase6_4_3() + { + ByteBuffer payload = ByteBuffer.allocate(64); + BufferUtil.clearToFill(payload); + payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good + payload.put(TypeUtil.fromHexString("f4908080")); // INVALID + payload.put(TypeUtil.fromHexString("656469746564")); // good + BufferUtil.flipToFlush(payload,0); + + WebSocketFrame text = new WebSocketFrame(); + text.setMask(TypeUtil.fromHexString("11223344")); + text.setPayload(payload); + text.setOpCode(OpCode.TEXT); + + ByteBuffer buf = new UnitGenerator().generate(text); + + ByteBuffer part1 = ByteBuffer.allocate(17); // header + good + ByteBuffer part2 = ByteBuffer.allocate(4); // invalid + ByteBuffer part3 = ByteBuffer.allocate(10); // the rest (all good utf) + + BufferUtil.put(buf,part1); + BufferUtil.put(buf,part2); + BufferUtil.put(buf,part3); + + BufferUtil.flipToFlush(part1,0); + BufferUtil.flipToFlush(part2,0); + BufferUtil.flipToFlush(part3,0); + + LOG.debug("Part1: {}",BufferUtil.toDetailString(part1)); + LOG.debug("Part2: {}",BufferUtil.toDetailString(part2)); + LOG.debug("Part3: {}",BufferUtil.toDetailString(part3)); + + UnitParser parser = new UnitParser(); + IncomingFramesCapture capture = new IncomingFramesCapture(); + parser.setIncomingFramesHandler(capture); + + parser.parse(part1); + capture.assertErrorCount(0); + parser.parse(part2); + capture.assertErrorCount(1); + capture.assertHasErrors(BadPayloadException.class,1); + } + @Test public void testParseNothing() { diff --git a/jetty-websocket/websocket-core/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-core/src/test/resources/jetty-logging.properties index c100df43afe..6e23a7d69e9 100644 --- a/jetty-websocket/websocket-core/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-core/src/test/resources/jetty-logging.properties @@ -1,3 +1,5 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.websocket.LEVEL=WARN -# org.eclipse.jetty.websocket.protocol.Parser.LEVEL=DEBUG \ No newline at end of file +# org.eclipse.jetty.websocket.protocol.Parser.LEVEL=DEBUG +# org.eclipse.jetty.websocket.protocol.LEVEL=DEBUG +# org.eclipse.jetty.websocket.io.payload.LEVEL=DEBUG \ No newline at end of file diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java index 6834d78acc8..8371fc14246 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java @@ -22,7 +22,9 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.toolchain.test.AdvancedRunner; import org.eclipse.jetty.toolchain.test.annotation.Slow; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.protocol.CloseInfo; import org.eclipse.jetty.websocket.protocol.OpCode; @@ -351,10 +353,15 @@ public class TestABCase6 extends AbstractABCase @Slow public void testCase6_4_3() throws Exception { - byte invalid[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5F49080808080656469746564"); + ByteBuffer payload = ByteBuffer.allocate(64); + BufferUtil.clearToFill(payload); + payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good + payload.put(TypeUtil.fromHexString("f4908080")); // INVALID + payload.put(TypeUtil.fromHexString("656469746564")); // good + BufferUtil.flipToFlush(payload,0); List send = new ArrayList<>(); - send.add(new WebSocketFrame(OpCode.TEXT).setPayload(invalid)); + send.add(new WebSocketFrame(OpCode.TEXT).setPayload(payload)); send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); List expect = new ArrayList<>(); @@ -366,14 +373,27 @@ public class TestABCase6 extends AbstractABCase fuzzer.connect(); ByteBuffer net = fuzzer.asNetworkBuffer(send); - fuzzer.send(net,6); - fuzzer.send(net,11); + + int splits[] = + { 17, 21, net.limit() }; + + ByteBuffer part1 = net.slice(); // Header + good UTF + part1.limit(splits[0]); + ByteBuffer part2 = net.slice(); // invalid UTF + part2.position(splits[0]); + part2.limit(splits[1]); + ByteBuffer part3 = net.slice(); // good UTF + part3.position(splits[1]); + part3.limit(splits[2]); + + fuzzer.send(part1); // the header + good utf TimeUnit.SECONDS.sleep(1); - fuzzer.send(net,4); - TimeUnit.SECONDS.sleep(1); - fuzzer.send(net,100); // the rest + fuzzer.send(part2); // the bad UTF fuzzer.expect(expect); + + TimeUnit.SECONDS.sleep(1); + fuzzer.send(part3); // the rest (shouldn't work) } finally { diff --git a/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties index ff2072e284d..0e6cda6a6b8 100644 --- a/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties @@ -17,6 +17,7 @@ org.eclipse.jetty.websocket.server.helper.RFCSocket.LEVEL=OFF # org.eclipse.jetty.websocket.extensions.LEVEL=DEBUG # org.eclipse.jetty.websocket.protocol.Generator.LEVEL=INFO # org.eclipse.jetty.websocket.protocol.Parser.LEVEL=DEBUG +# org.eclipse.jetty.websocket.io.payload.LEVEL=DEBUG # org.eclipse.jetty.websocket.server.ab.LEVEL=DEBUG # org.eclipse.jetty.websocket.server.ab.Fuzzer.LEVEL=DEBUG # org.eclipse.jetty.websocket.server.blockhead.LEVEL=DEBUG \ No newline at end of file