Search in sources :

Example 1 with ProtocolException

use of org.eclipse.jetty.websocket.api.ProtocolException in project jetty.project by eclipse.

the class TestABCase4 method testParserNonControlOpCode3Case4_1_1.

@Test
public void testParserNonControlOpCode3Case4_1_1() throws Exception {
    ByteBuffer expected = ByteBuffer.allocate(32);
    expected.put(new byte[] { (byte) 0x83, 0x00 });
    expected.flip();
    IncomingFramesCapture capture = new IncomingFramesCapture();
    try (StacklessLogging logging = new StacklessLogging(Parser.class)) {
        Parser parser = new UnitParser(policy);
        parser.setIncomingFramesHandler(capture);
        try {
            parser.parse(expected);
        } catch (ProtocolException ignore) {
        // ignore
        }
    }
    Assert.assertEquals("error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class));
    Throwable known = capture.getErrors().poll();
    Assert.assertTrue("undefined option should be in message", known.getMessage().contains("Unknown opcode: 3"));
}
Also used : ProtocolException(org.eclipse.jetty.websocket.api.ProtocolException) WebSocketException(org.eclipse.jetty.websocket.api.WebSocketException) IncomingFramesCapture(org.eclipse.jetty.websocket.common.test.IncomingFramesCapture) StacklessLogging(org.eclipse.jetty.util.log.StacklessLogging) UnitParser(org.eclipse.jetty.websocket.common.test.UnitParser) ByteBuffer(java.nio.ByteBuffer) Parser(org.eclipse.jetty.websocket.common.Parser) UnitParser(org.eclipse.jetty.websocket.common.test.UnitParser) Test(org.junit.Test)

Example 2 with ProtocolException

use of org.eclipse.jetty.websocket.api.ProtocolException in project jetty.project by eclipse.

the class TestABCase4 method testParserControlOpCode12WithPayloadCase4_2_2.

@Test
public void testParserControlOpCode12WithPayloadCase4_2_2() throws Exception {
    ByteBuffer expected = ByteBuffer.allocate(32);
    expected.put(new byte[] { (byte) 0x8c, 0x01, 0x00 });
    expected.flip();
    IncomingFramesCapture capture = new IncomingFramesCapture();
    try (StacklessLogging logging = new StacklessLogging(Parser.class)) {
        Parser parser = new UnitParser(policy);
        parser.setIncomingFramesHandler(capture);
        try {
            parser.parse(expected);
        } catch (ProtocolException ignore) {
        // ignore
        }
    }
    Assert.assertEquals("error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class));
    Throwable known = capture.getErrors().poll();
    Assert.assertTrue("undefined option should be in message", known.getMessage().contains("Unknown opcode: 12"));
}
Also used : ProtocolException(org.eclipse.jetty.websocket.api.ProtocolException) WebSocketException(org.eclipse.jetty.websocket.api.WebSocketException) IncomingFramesCapture(org.eclipse.jetty.websocket.common.test.IncomingFramesCapture) StacklessLogging(org.eclipse.jetty.util.log.StacklessLogging) UnitParser(org.eclipse.jetty.websocket.common.test.UnitParser) ByteBuffer(java.nio.ByteBuffer) Parser(org.eclipse.jetty.websocket.common.Parser) UnitParser(org.eclipse.jetty.websocket.common.test.UnitParser) Test(org.junit.Test)

Example 3 with ProtocolException

use of org.eclipse.jetty.websocket.api.ProtocolException in project jetty.project by eclipse.

the class TestABCase4 method testParserControlOpCode11Case4_2_1.

@Test
public void testParserControlOpCode11Case4_2_1() throws Exception {
    ByteBuffer expected = ByteBuffer.allocate(32);
    expected.put(new byte[] { (byte) 0x8b, 0x00 });
    expected.flip();
    IncomingFramesCapture capture = new IncomingFramesCapture();
    try (StacklessLogging logging = new StacklessLogging(Parser.class)) {
        Parser parser = new UnitParser(policy);
        parser.setIncomingFramesHandler(capture);
        try {
            parser.parse(expected);
        } catch (ProtocolException ignore) {
        // ignore
        }
    }
    Assert.assertEquals("error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class));
    Throwable known = capture.getErrors().poll();
    Assert.assertTrue("undefined option should be in message", known.getMessage().contains("Unknown opcode: 11"));
}
Also used : ProtocolException(org.eclipse.jetty.websocket.api.ProtocolException) WebSocketException(org.eclipse.jetty.websocket.api.WebSocketException) IncomingFramesCapture(org.eclipse.jetty.websocket.common.test.IncomingFramesCapture) StacklessLogging(org.eclipse.jetty.util.log.StacklessLogging) UnitParser(org.eclipse.jetty.websocket.common.test.UnitParser) ByteBuffer(java.nio.ByteBuffer) Parser(org.eclipse.jetty.websocket.common.Parser) UnitParser(org.eclipse.jetty.websocket.common.test.UnitParser) Test(org.junit.Test)

Example 4 with ProtocolException

use of org.eclipse.jetty.websocket.api.ProtocolException in project jetty.project by eclipse.

the class Parser method parseFrame.

/**
     * Parse the base framing protocol buffer.
     * <p>
     * Note the first byte (fin,rsv1,rsv2,rsv3,opcode) are parsed by the {@link Parser#parse(ByteBuffer)} method
     * <p>
     * Not overridable
     * 
     * @param buffer
     *            the buffer to parse from.
     * @return true if done parsing base framing protocol and ready for parsing of the payload. false if incomplete parsing of base framing protocol.
     */
private boolean parseFrame(ByteBuffer buffer) {
    if (LOG.isDebugEnabled()) {
        LOG.debug("{} Parsing {} bytes", policy.getBehavior(), buffer.remaining());
    }
    while (buffer.hasRemaining()) {
        switch(state) {
            case START:
                {
                    // peek at byte
                    byte b = buffer.get();
                    boolean fin = ((b & 0x80) != 0);
                    byte opcode = (byte) (b & 0x0F);
                    if (!OpCode.isKnown(opcode)) {
                        throw new ProtocolException("Unknown opcode: " + opcode);
                    }
                    if (LOG.isDebugEnabled())
                        LOG.debug("{} OpCode {}, fin={} rsv={}{}{}", policy.getBehavior(), OpCode.name(opcode), fin, (((b & 0x40) != 0) ? '1' : '.'), (((b & 0x20) != 0) ? '1' : '.'), (((b & 0x10) != 0) ? '1' : '.'));
                    // base framing flags
                    switch(opcode) {
                        case OpCode.TEXT:
                            frame = new TextFrame();
                            // data validation
                            if (priorDataFrame) {
                                throw new ProtocolException("Unexpected " + OpCode.name(opcode) + " frame, was expecting CONTINUATION");
                            }
                            break;
                        case OpCode.BINARY:
                            frame = new BinaryFrame();
                            // data validation
                            if (priorDataFrame) {
                                throw new ProtocolException("Unexpected " + OpCode.name(opcode) + " frame, was expecting CONTINUATION");
                            }
                            break;
                        case OpCode.CONTINUATION:
                            frame = new ContinuationFrame();
                            // continuation validation
                            if (!priorDataFrame) {
                                throw new ProtocolException("CONTINUATION frame without prior !FIN");
                            }
                            // Be careful to use the original opcode
                            break;
                        case OpCode.CLOSE:
                            frame = new CloseFrame();
                            // control frame validation
                            if (!fin) {
                                throw new ProtocolException("Fragmented Close Frame [" + OpCode.name(opcode) + "]");
                            }
                            break;
                        case OpCode.PING:
                            frame = new PingFrame();
                            // control frame validation
                            if (!fin) {
                                throw new ProtocolException("Fragmented Ping Frame [" + OpCode.name(opcode) + "]");
                            }
                            break;
                        case OpCode.PONG:
                            frame = new PongFrame();
                            // control frame validation
                            if (!fin) {
                                throw new ProtocolException("Fragmented Pong Frame [" + OpCode.name(opcode) + "]");
                            }
                            break;
                    }
                    frame.setFin(fin);
                    // Are any flags set?
                    if ((b & 0x70) != 0) {
                        /*
                         * RFC 6455 Section 5.2
                         * 
                         * MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. If a nonzero value is received and none of the
                         * negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST _Fail the WebSocket Connection_.
                         */
                        if ((b & 0x40) != 0) {
                            if (isRsv1InUse())
                                frame.setRsv1(true);
                            else {
                                String err = "RSV1 not allowed to be set";
                                if (LOG.isDebugEnabled()) {
                                    LOG.debug(err + ": Remaining buffer: {}", BufferUtil.toDetailString(buffer));
                                }
                                throw new ProtocolException(err);
                            }
                        }
                        if ((b & 0x20) != 0) {
                            if (isRsv2InUse())
                                frame.setRsv2(true);
                            else {
                                String err = "RSV2 not allowed to be set";
                                if (LOG.isDebugEnabled()) {
                                    LOG.debug(err + ": Remaining buffer: {}", BufferUtil.toDetailString(buffer));
                                }
                                throw new ProtocolException(err);
                            }
                        }
                        if ((b & 0x10) != 0) {
                            if (isRsv3InUse())
                                frame.setRsv3(true);
                            else {
                                String err = "RSV3 not allowed to be set";
                                if (LOG.isDebugEnabled()) {
                                    LOG.debug(err + ": Remaining buffer: {}", BufferUtil.toDetailString(buffer));
                                }
                                throw new ProtocolException(err);
                            }
                        }
                    }
                    state = State.PAYLOAD_LEN;
                    break;
                }
            case PAYLOAD_LEN:
                {
                    byte b = buffer.get();
                    frame.setMasked((b & 0x80) != 0);
                    payloadLength = (byte) (0x7F & b);
                    if (// 0x7F
                    payloadLength == 127) {
                        // length 8 bytes (extended payload length)
                        payloadLength = 0;
                        state = State.PAYLOAD_LEN_BYTES;
                        cursor = 8;
                        // continue onto next state
                        break;
                    } else if (// 0x7E
                    payloadLength == 126) {
                        // length 2 bytes (extended payload length)
                        payloadLength = 0;
                        state = State.PAYLOAD_LEN_BYTES;
                        cursor = 2;
                        // continue onto next state
                        break;
                    }
                    assertSanePayloadLength(payloadLength);
                    if (frame.isMasked()) {
                        state = State.MASK;
                    } else {
                        // special case for empty payloads (no more bytes left in buffer)
                        if (payloadLength == 0) {
                            state = State.START;
                            return true;
                        }
                        maskProcessor.reset(frame);
                        state = State.PAYLOAD;
                    }
                    break;
                }
            case PAYLOAD_LEN_BYTES:
                {
                    byte b = buffer.get();
                    --cursor;
                    payloadLength |= (b & 0xFF) << (8 * cursor);
                    if (cursor == 0) {
                        assertSanePayloadLength(payloadLength);
                        if (frame.isMasked()) {
                            state = State.MASK;
                        } else {
                            // special case for empty payloads (no more bytes left in buffer)
                            if (payloadLength == 0) {
                                state = State.START;
                                return true;
                            }
                            maskProcessor.reset(frame);
                            state = State.PAYLOAD;
                        }
                    }
                    break;
                }
            case MASK:
                {
                    byte[] m = new byte[4];
                    frame.setMask(m);
                    if (buffer.remaining() >= 4) {
                        buffer.get(m, 0, 4);
                        // special case for empty payloads (no more bytes left in buffer)
                        if (payloadLength == 0) {
                            state = State.START;
                            return true;
                        }
                        maskProcessor.reset(frame);
                        state = State.PAYLOAD;
                    } else {
                        state = State.MASK_BYTES;
                        cursor = 4;
                    }
                    break;
                }
            case MASK_BYTES:
                {
                    byte b = buffer.get();
                    frame.getMask()[4 - cursor] = b;
                    --cursor;
                    if (cursor == 0) {
                        // special case for empty payloads (no more bytes left in buffer)
                        if (payloadLength == 0) {
                            state = State.START;
                            return true;
                        }
                        maskProcessor.reset(frame);
                        state = State.PAYLOAD;
                    }
                    break;
                }
            case PAYLOAD:
                {
                    frame.assertValid();
                    if (parsePayload(buffer)) {
                        // special check for close
                        if (frame.getOpCode() == OpCode.CLOSE) {
                            // TODO: yuck. Don't create an object to do validation checks!
                            new CloseInfo(frame);
                        }
                        state = State.START;
                        // we have a frame!
                        return true;
                    }
                    break;
                }
        }
    }
    return false;
}
Also used : PongFrame(org.eclipse.jetty.websocket.common.frames.PongFrame) ProtocolException(org.eclipse.jetty.websocket.api.ProtocolException) BinaryFrame(org.eclipse.jetty.websocket.common.frames.BinaryFrame) PingFrame(org.eclipse.jetty.websocket.common.frames.PingFrame) TextFrame(org.eclipse.jetty.websocket.common.frames.TextFrame) CloseFrame(org.eclipse.jetty.websocket.common.frames.CloseFrame) ContinuationFrame(org.eclipse.jetty.websocket.common.frames.ContinuationFrame)

Example 5 with ProtocolException

use of org.eclipse.jetty.websocket.api.ProtocolException in project jetty.project by eclipse.

the class CloseInfo method asFrame.

public CloseFrame asFrame() {
    CloseFrame frame = new CloseFrame();
    frame.setFin(true);
    if ((statusCode >= 1000) && (statusCode != StatusCode.NO_CLOSE) && (statusCode != StatusCode.NO_CODE)) {
        if (statusCode == StatusCode.FAILED_TLS_HANDSHAKE) {
            throw new ProtocolException("Close Frame with status code " + statusCode + " not allowed (per RFC6455)");
        }
        frame.setPayload(asByteBuffer());
    }
    return frame;
}
Also used : ProtocolException(org.eclipse.jetty.websocket.api.ProtocolException) CloseFrame(org.eclipse.jetty.websocket.common.frames.CloseFrame)

Aggregations

ProtocolException (org.eclipse.jetty.websocket.api.ProtocolException)9 Test (org.junit.Test)7 ByteBuffer (java.nio.ByteBuffer)6 IncomingFramesCapture (org.eclipse.jetty.websocket.common.test.IncomingFramesCapture)6 UnitParser (org.eclipse.jetty.websocket.common.test.UnitParser)6 StacklessLogging (org.eclipse.jetty.util.log.StacklessLogging)4 WebSocketException (org.eclipse.jetty.websocket.api.WebSocketException)4 Parser (org.eclipse.jetty.websocket.common.Parser)4 CloseFrame (org.eclipse.jetty.websocket.common.frames.CloseFrame)3 BinaryFrame (org.eclipse.jetty.websocket.common.frames.BinaryFrame)1 ContinuationFrame (org.eclipse.jetty.websocket.common.frames.ContinuationFrame)1 PingFrame (org.eclipse.jetty.websocket.common.frames.PingFrame)1 PongFrame (org.eclipse.jetty.websocket.common.frames.PongFrame)1 TextFrame (org.eclipse.jetty.websocket.common.frames.TextFrame)1