blob: 5b8e2f9abd9a039b6ba762c97233a9f38ae56dd8 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.common.ab;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.frames.CloseFrame;
import org.eclipse.jetty.websocket.common.test.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture;
import org.eclipse.jetty.websocket.common.test.UnitGenerator;
import org.eclipse.jetty.websocket.common.test.UnitParser;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.junit.Assert;
import org.junit.Test;
public class TestABCase7_3
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT);
@Test
public void testCase7_3_1GenerateEmptyClose()
{
CloseInfo close = new CloseInfo();
ByteBuffer actual = UnitGenerator.generate(close.asFrame());
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x00 });
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testCase7_3_1ParseEmptyClose()
{
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x00 });
expected.flip();
Parser parser = new UnitParser(policy);
IncomingFramesCapture capture = new IncomingFramesCapture();
parser.setIncomingFramesHandler(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1);
Frame pActual = capture.getFrames().poll();
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0));
}
@Test(expected = ProtocolException.class)
public void testCase7_3_2Generate1BytePayloadClose()
{
CloseFrame closeFrame = new CloseFrame();
closeFrame.setPayload(Hex.asByteBuffer("00"));
UnitGenerator.generate(closeFrame);
}
@Test
public void testCase7_3_2Parse1BytePayloadClose()
{
ByteBuffer expected = Hex.asByteBuffer("880100");
UnitParser parser = new UnitParser(policy);
IncomingFramesCapture capture = new IncomingFramesCapture();
parser.setIncomingFramesHandler(capture);
parser.parseQuietly(expected);
Assert.assertEquals("error on invalid close payload",1,capture.getErrorCount(ProtocolException.class));
ProtocolException known = (ProtocolException)capture.getErrors().poll();
Assert.assertThat("Payload.message",known.getMessage(),containsString("Invalid close frame payload length"));
}
@Test
public void testCase7_3_3GenerateCloseWithStatus()
{
CloseInfo close = new CloseInfo(1000);
ByteBuffer actual = UnitGenerator.generate(close.asFrame());
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 });
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testCase7_3_3ParseCloseWithStatus()
{
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 });
expected.flip();
Parser parser = new UnitParser(policy);
IncomingFramesCapture capture = new IncomingFramesCapture();
parser.setIncomingFramesHandler(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1);
Frame pActual = capture.getFrames().poll();
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2));
}
@Test
public void testCase7_3_4GenerateCloseWithStatusReason()
{
String message = "bad cough";
byte[] messageBytes = message.getBytes();
CloseInfo close = new CloseInfo(1000,message);
ByteBuffer actual = UnitGenerator.generate(close.asFrame());
ByteBuffer expected = ByteBuffer.allocate(32);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (message.length() + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testCase7_3_4ParseCloseWithStatusReason()
{
String message = "bad cough";
byte[] messageBytes = message.getBytes();
ByteBuffer expected = ByteBuffer.allocate(32);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
Parser parser = new UnitParser(policy);
IncomingFramesCapture capture = new IncomingFramesCapture();
parser.setIncomingFramesHandler(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1);
Frame pActual = capture.getFrames().poll();
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2));
}
@Test
public void testCase7_3_5GenerateCloseWithStatusMaxReason()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 123 ; ++i )
{
message.append("*");
}
CloseInfo close = new CloseInfo(1000,message.toString());
ByteBuffer actual = UnitGenerator.generate(close.asFrame());
ByteBuffer expected = ByteBuffer.allocate(132);
byte messageBytes[] = message.toString().getBytes(StandardCharsets.UTF_8);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testCase7_3_5ParseCloseWithStatusMaxReason()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 123 ; ++i )
{
message.append("*");
}
byte[] messageBytes = message.toString().getBytes(StandardCharsets.UTF_8);
ByteBuffer expected = ByteBuffer.allocate(132);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
Parser parser = new UnitParser(policy);
IncomingFramesCapture capture = new IncomingFramesCapture();
parser.setIncomingFramesHandler(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1);
Frame pActual = capture.getFrames().poll();
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125));
}
@Test(expected = ProtocolException.class)
public void testCase7_3_6GenerateCloseWithInvalidStatusReason()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 124 ; ++i )
{
message.append("*");
}
byte[] messageBytes = message.toString().getBytes();
CloseFrame closeFrame = new CloseFrame();
ByteBuffer bb = ByteBuffer.allocate(CloseFrame.MAX_CONTROL_PAYLOAD + 1); // 126 which is too big for control
bb.putChar((char)1000);
bb.put(messageBytes);
BufferUtil.flipToFlush(bb,0);
closeFrame.setPayload(bb);
UnitGenerator.generate(closeFrame);
}
@Test
public void testCase7_3_6ParseCloseWithInvalidStatusReason()
{
byte[] messageBytes = new byte[124];
Arrays.fill(messageBytes,(byte)'*');
ByteBuffer expected = ByteBuffer.allocate(256);
byte b;
// fin + op
b = 0x00;
b |= 0x80; // fin on
b |= 0x08; // close
expected.put(b);
// mask + len
b = 0x00;
b |= 0x00; // no masking
b |= 0x7E; // 2 byte len
expected.put(b);
// 2 byte len
expected.putChar((char)(messageBytes.length + 2));
// payload
expected.putShort((short)1000); // status code
expected.put(messageBytes); // reason
expected.flip();
UnitParser parser = new UnitParser(policy);
IncomingFramesCapture capture = new IncomingFramesCapture();
parser.setIncomingFramesHandler(capture);
parser.parseQuietly(expected);
Assert.assertEquals("error on invalid close payload",1,capture.getErrorCount(ProtocolException.class));
ProtocolException known = (ProtocolException)capture.getErrors().poll();
Assert.assertThat("Payload.message",known.getMessage(),containsString("Invalid control frame payload length"));
}
}