diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/CloseInfo.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/CloseInfo.java new file mode 100644 index 00000000000..193b204dfef --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/CloseInfo.java @@ -0,0 +1,83 @@ +package org.eclipse.jetty.websocket.protocol; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.ProtocolException; +import org.eclipse.jetty.websocket.api.StatusCode; + +public class CloseInfo +{ + private static final Logger LOG = Log.getLogger(CloseInfo.class); + private int statusCode; + private String reason; + + public CloseInfo(byte payload[], boolean validate) + { + this.statusCode = 0; + this.reason = null; + + if ((payload == null) || (payload.length == 0)) + { + return; // nothing to do + } + + if ((payload.length == 1) && (validate)) + { + throw new ProtocolException("Invalid 1 byte payload"); + } + + if (payload.length >= 2) + { + // Status Code + ByteBuffer bb = ByteBuffer.wrap(payload); + statusCode |= (bb.get(0) & 0xFF) << 8; + statusCode |= (bb.get(1) & 0xFF); + + if(validate) { + if ((statusCode < StatusCode.NORMAL) || (statusCode == StatusCode.UNDEFINED) || (statusCode == StatusCode.NO_CLOSE) + || (statusCode == StatusCode.NO_CODE) || ((statusCode > 1011) && (statusCode <= 2999)) || (statusCode >= 5000)) + { + throw new ProtocolException("Invalid close code: " + statusCode); + } + } + + if (payload.length > 2) + { + // Reason + try + { + reason = StringUtil.toUTF8String(payload,2,payload.length - 2); + } + catch (RuntimeException e) + { + if (validate) + { + throw new ProtocolException("Invalid Close Reason:",e); + } + else + { + LOG.warn(e); + } + } + } + } + } + + public CloseInfo(WebSocketFrame frame) + { + this(frame.getPayloadData(),false); + } + + public String getReason() + { + return reason; + } + + public int getStatusCode() + { + return statusCode; + } +} diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java index 415d9993985..4205fbe7c7e 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java @@ -74,7 +74,7 @@ public class GeneratorParserRoundtripTest try { // Setup Frame - TextFrame txt = (TextFrame)FrameBuilder.text().payload(message.getBytes()).asFrame(); + WebSocketFrame txt = FrameBuilder.text().payload(message.getBytes()).asFrame(); // Add masking byte mask[] = new byte[4]; @@ -96,10 +96,10 @@ public class GeneratorParserRoundtripTest // Validate capture.assertNoErrors(); - capture.assertHasFrame(TextFrame.class,1); + capture.assertHasFrame(OpCode.TEXT,1); - TextFrame txt = (TextFrame)capture.getFrames().get(0); + WebSocketFrame txt = capture.getFrames().get(0); Assert.assertTrue("Text.isMasked",txt.isMasked()); - Assert.assertThat("Text parsed",txt.getPayloadUTF8(),is(message)); + Assert.assertThat("Text parsed",txt.getPayloadAsUTF8(),is(message)); } } diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java index c9439b6efc8..1b7c2b071c3 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java @@ -1,6 +1,6 @@ package org.eclipse.jetty.websocket.parser; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; import java.nio.ByteBuffer; @@ -8,7 +8,7 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.frames.CloseFrame; +import org.eclipse.jetty.websocket.protocol.CloseInfo; import org.eclipse.jetty.websocket.protocol.OpCode; import org.junit.Assert; import org.junit.Test; @@ -40,8 +40,8 @@ public class ClosePayloadParserTest parser.parse(buf); capture.assertNoErrors(); - capture.assertHasFrame(CloseFrame.class,1); - CloseFrame close = (CloseFrame)capture.getFrames().get(0); + capture.assertHasFrame(OpCode.CLOSE,1); + CloseInfo close = new CloseInfo(capture.getFrames().get(0)); Assert.assertThat("CloseFrame.statusCode",close.getStatusCode(),is(StatusCode.NORMAL)); Assert.assertThat("CloseFrame.data",close.getReason(),is(expectedReason)); }