// Decode a 200-byte binary frame
  private void sizeLimitDecodeBinaryFrame(int maxSize) throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, maxSize);

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(204))
            .put((byte) 0x82)
            .put((byte) 126)
            .put((byte) 0x00)
            .put((byte) 0xC8)
            .fill(200)
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsBinaryMessage(allocator.wrap(allocator.allocate(200)).fill(200).flip()), out);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }
  @Test
  public void decodeZeroLengthMaskedPongFrame() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 0);

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(6))
            .put((byte) 0x8A)
            .put((byte) 0x80)
            .fill(4) // mask
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsPongMessage(allocator.wrap(allocator.allocate(0)).flip()), out);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }
  @Test
  public void decodeTextContinuationFrameWithFragmentedPayload() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 250);

    String textFramePayload = createString('a', 100);
    String continuationFramePayloadFirstFragment = createString('b', 50);
    String continuationFramePayloadSecondFragment = createString('b', 50);

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(102))
            // text frame
            .put((byte) 0x01)
            .put((byte) 100)
            .putString(textFramePayload, UTF_8.newEncoder())
            .flip();

    IoBufferEx[] array =
        new IoBufferEx[] {
          allocator
              .wrap(allocator.allocate(2))
              // continuation frame fragment (opcode and payload length)
              .put((byte) 0x80)
              .put((byte) 0x64)
              .flip(),
          allocator
              .wrap(allocator.allocate(50))
              // continuation frame payload first fragment
              .putString(continuationFramePayloadFirstFragment, UTF_8.newEncoder())
              .flip(),
          allocator
              .wrap(allocator.allocate(50))
              // continuation frame payload second fragment
              .putString(continuationFramePayloadSecondFragment, UTF_8.newEncoder())
              .flip()
        };
    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    for (IoBufferEx buffer : array) {
      decoder.decode(session, (IoBuffer) buffer, session.getDecoderOutput());
    }

    WsMessage out1 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsTextMessage(allocator.wrap(ByteBuffer.wrap(textFramePayload.getBytes(UTF_8))), false),
        out1);

    WsMessage out2 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsContinuationMessage(
            allocator.wrap(ByteBuffer.wrap(createString('b', 100).getBytes(UTF_8)))),
        out2);
  }
  @Test
  public void decodeBinaryContinuationFrameWithFragmentedPayload() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 250);

    byte[] binaryFramePayload = createString('a', 100).getBytes();
    byte[] continuationFramePayload = createString('b', 100).getBytes();

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(102))
            // binary frame
            .put((byte) 0x02)
            .put((byte) 100)
            .put(binaryFramePayload)
            .flip();

    IoBufferEx[] array =
        new IoBufferEx[] {
          allocator
              .wrap(allocator.allocate(2))
              // continuation frame fragment (opcode and payload length)
              .put((byte) 0x80)
              .put((byte) 0x64)
              .flip(),
          allocator
              .wrap(allocator.allocate(50))
              // continuation frame first fragment
              .put(continuationFramePayload, 0, 50)
              .flip(),
          allocator
              .wrap(allocator.allocate(50))
              // continuation frame second fragment
              .put(continuationFramePayload, 50, 50)
              .flip()
        };
    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    for (IoBufferEx buffer : array) {
      decoder.decode(session, (IoBuffer) buffer, session.getDecoderOutput());
    }

    WsMessage out1 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsBinaryMessage(allocator.wrap(ByteBuffer.wrap(binaryFramePayload)), false), out1);

    WsMessage out2 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsContinuationMessage(allocator.wrap(ByteBuffer.wrap(continuationFramePayload))), out2);
  }
  @Test
  public void decodeTextFrame() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 0);

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(14))
            .put((byte) 0x81)
            .put((byte) 0x0C)
            .putString("Hello, world", UTF_8.newEncoder())
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsTextMessage(allocator.wrap(ByteBuffer.wrap("Hello, world".getBytes(UTF_8)))), out);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }
  /** {@inheritDoc} */
  @Override
  public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception {
    IoBufferEx inEx = (IoBufferEx) in;
    if (buffer == null) {
      if (in.remaining() >= length) {
        int limit = in.limit();
        in.limit(in.position() + length);
        IoBufferEx product = inEx.slice();
        in.position(in.position() + length);
        in.limit(limit);
        return finishDecode((IoBuffer) product, out);
      }

      buffer = allocator.wrap(allocator.allocate(length));
      buffer.put(inEx);
      return this;
    }

    if (in.remaining() >= length - buffer.position()) {
      int limit = in.limit();
      in.limit(in.position() + length - buffer.position());
      buffer.put(inEx);
      in.limit(limit);
      buffer.flip();
      IoBufferEx product = buffer;
      buffer = null;
      return finishDecode((IoBuffer) product, out);
    }

    buffer.put(inEx);
    return this;
  }
  // Decode a 12-byte text frame and a 15 byte text frame written in one go (one network packet)
  private void sizeLimitDecodeDoubleTextFrame(int maxSize) throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, maxSize);

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(12 + 2 + 15 + 2))
            .put((byte) 0x81)
            .put((byte) 12)
            .putString("123456789012", UTF_8.newEncoder())
            .put((byte) 0x81)
            .put((byte) 15)
            .putString("123456789012345", UTF_8.newEncoder())
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsTextMessage(allocator.wrap(ByteBuffer.wrap("123456789012".getBytes(UTF_8)))), out);

    WsMessage out2 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsTextMessage(allocator.wrap(ByteBuffer.wrap("123456789012345".getBytes(UTF_8)))),
        out2);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }
  @Test
  public void decodeFragmentedBinaryFrame() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 0);

    IoBufferEx[] array =
        new IoBufferEx[] {
          allocator
              .wrap(allocator.allocate(104))
              .put((byte) 0x82)
              .put((byte) 126)
              .put((byte) 0x00)
              .put((byte) 0xC8)
              .fill(100)
              .flip(),
          allocator
              .wrap(allocator.allocate(102))
              .fill(100)
              .put((byte) 0x82)
              .put((byte) 0x00)
              .flip(),
        };

    for (IoBufferEx in : array) {
      decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());
    }

    WsMessage fragmented = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsBinaryMessage(allocator.wrap(allocator.allocate(200)).fill(200).flip()), fragmented);

    WsMessage empty = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsBinaryMessage(allocator.wrap(allocator.allocate(0))), empty);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());

    for (IoBufferEx in : array) {
      assertFalse(in.hasRemaining());
    }
  }
  @Test
  public void decodeFragmentedTextFrame() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 0);

    IoBufferEx[] array =
        new IoBufferEx[] {
          allocator
              .wrap(allocator.allocate(103))
              .put((byte) 0x81)
              .put((byte) 0x0C)
              .putString("Hello", UTF_8.newEncoder())
              .flip(),
          allocator
              .wrap(allocator.allocate(102))
              .putString(", world", UTF_8.newEncoder())
              .put((byte) 0x81)
              .put((byte) 0x00)
              .flip(),
        };

    for (IoBufferEx in : array) {
      decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());
    }

    WsMessage fragmented = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsTextMessage(allocator.wrap(ByteBuffer.wrap("Hello, world".getBytes(UTF_8)))),
        fragmented);

    WsMessage empty = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsTextMessage(allocator.wrap(allocator.allocate(0))), empty);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());

    for (IoBufferEx in : array) {
      assertFalse(in.hasRemaining());
    }
  }
 /** {@inheritDoc} */
 @Override
 public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception {
   IoBufferEx readData;
   if (buffer == null) {
     readData = allocator.wrap(allocator.allocate(0));
   } else {
     buffer.flip();
     readData = buffer;
     buffer = null;
   }
   return finishDecode((IoBuffer) readData, out);
 }
  @Test
  public void decodeTextContinuationFrame() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 200);

    int firstPayload = 125;
    String first = createString('a', firstPayload);

    int secondPayload = 2;
    String second = createString('b', secondPayload);

    int thirdPayload = 4;
    String thrid = createString('c', thirdPayload);

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(firstPayload + secondPayload + thirdPayload + 6))
            // text frame
            .put((byte) 0x01)
            .put((byte) firstPayload)
            .putString(first, UTF_8.newEncoder())
            // continuation frame with FIN
            .put((byte) 0x80)
            .put((byte) secondPayload)
            .putString(second, UTF_8.newEncoder())
            // text frame with FIN
            .put((byte) 0x81)
            .put((byte) thirdPayload)
            .putString(thrid, UTF_8.newEncoder())
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out1 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsTextMessage(allocator.wrap(ByteBuffer.wrap(first.getBytes(UTF_8))), false), out1);

    WsMessage out2 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsContinuationMessage(allocator.wrap(ByteBuffer.wrap(second.getBytes(UTF_8)))), out2);

    WsMessage out3 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsTextMessage(allocator.wrap(ByteBuffer.wrap(thrid.getBytes(UTF_8)))), out3);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }
  @Test
  public void decodeBinaryContinuationFrame() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 200);

    int firstPayload = 125;
    byte[] first = createString('a', firstPayload).getBytes("UTF-8");

    int secondPayload = 2;
    byte[] second = createString('b', secondPayload).getBytes("UTF-8");

    int thirdPayload = 4;
    byte[] thrid = createString('c', thirdPayload).getBytes("UTF-8");

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(firstPayload + secondPayload + thirdPayload + 6))
            // binary frame
            .put((byte) 0x02)
            .put((byte) firstPayload)
            .put(first)
            // continuation frame with FIN
            .put((byte) 0x80)
            .put((byte) secondPayload)
            .put(second)
            // binary frame with FIN
            .put((byte) 0x82)
            .put((byte) thirdPayload)
            .put(thrid)
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out1 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsBinaryMessage(allocator.wrap(ByteBuffer.wrap(first)), false), out1);

    WsMessage out2 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsContinuationMessage(allocator.wrap(ByteBuffer.wrap(second))), out2);

    WsMessage out3 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsBinaryMessage(allocator.wrap(ByteBuffer.wrap(thrid))), out3);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }
Exemple #13
0
        @Override
        protected void doMessageReceived(HttpSession createSession, Object message)
            throws Exception {
          // Handle fragmentation of response body
          IoBufferEx in = (IoBufferEx) message;

          IoBufferEx buf = CREATE_RESPONSE_KEY.get(createSession);
          if (buf == null) {
            IoBufferAllocatorEx<?> allocator = createSession.getBufferAllocator();
            buf = allocator.wrap(allocator.allocate(in.remaining())).setAutoExpander(allocator);
            CREATE_RESPONSE_KEY.set(createSession, buf);
          }

          buf.put(in);
        }
  @Test(expected = ProtocolDecoderException.class)
  public void decodeFragmentedContinuationFrameExceedingMaxMessageSize() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 150);

    String textFramePayload = createString('a', 100);

    IoBufferEx textFrameBuffer =
        allocator
            .wrap(allocator.allocate(102))
            // text frame
            .put((byte) 0x01)
            .put((byte) 100)
            .putString(textFramePayload, UTF_8.newEncoder())
            .flip();

    // the decoder should fail fast when message size exceeds the max message size without waiting
    // for
    // payload
    IoBufferEx continuationFrameBuffer =
        allocator
            .wrap(allocator.allocate(2))
            // continuation frame fragment (opcode and payload length)
            .put((byte) 0x80)
            .put((byte) 0x64)
            .flip();

    decoder.decode(session, (IoBuffer) textFrameBuffer, session.getDecoderOutput());

    // since the maximum message size is 150, the following statement will
    // cause the message size(200) to exceed maximum message size
    // The decoder should fail fast once the payload length is decoded regardless of the
    // availability of payload
    decoder.decode(session, (IoBuffer) continuationFrameBuffer, session.getDecoderOutput());
  }
  // Make sure we fail early for case of large text messages: we should fail as soon as we process
  // a network packet that exceeds the limit (first packet in this case)
  @Test(expected = ProtocolDecoderException.class)
  public void sizeLimitDecodeTextFrameFailEarly1() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 20);

    int dataSize = 30;
    StringBuilder data = new StringBuilder(dataSize);
    for (int i = 0; i < (dataSize); i++) {
      data.append((i % 10));
    }

    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(dataSize + 2))
            .put((byte) 0x81)
            .put((byte) 30)
            .putString(data.toString(), UTF_8.newEncoder())
            .flip();
    // As soon as we sent part of a message that exceeds the limit it should throw the exception
    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());
  }
  // Make sure we fail early for case of large text messages: we should fail as soon as we process
  // a network packet that exceeds the limit (2nd packet in this case)
  @Test(expected = ProtocolDecoderException.class)
  public void sizeLimitDecodeTextFrameFailEarly2() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 20);

    int dataSize = 30;
    StringBuilder data = new StringBuilder(dataSize);
    for (int i = 0; i < (dataSize); i++) {
      data.append((i % 10));
    }
    IoBufferEx in =
        allocator
            .wrap(allocator.allocate(dataSize + 2))
            .put((byte) 0x81)
            .put((byte) 30)
            .putString(data.toString(), UTF_8.newEncoder())
            .flip();
    decoder.decode(session, (IoBuffer) in.getSlice(10), session.getDecoderOutput());
    // Now if we send the next 12 bytes that should exceed the limit (first byte is control byte,
    // doesn't count)
    decoder.decode(session, (IoBuffer) in.getSlice(12), session.getDecoderOutput());
  }
  private IoBufferEx getMaxMessageSizeBuffer(IoBufferAllocatorEx<?> allocator) throws Exception {
    int firstPayload = 125;
    String first = createString('a', firstPayload);

    int secondPayload = 125;
    String second = createString('b', secondPayload);

    int thirdPayload = 4;
    String third = createString('c', thirdPayload);

    int fourthPayload = 6;
    byte[] fourth = createString('d', fourthPayload).getBytes("UTF-8");

    return allocator
        .wrap(
            allocator.allocate(firstPayload + secondPayload + 2 + thirdPayload + fourthPayload + 8))
        // text frame
        .put((byte) 0x01)
        .put((byte) firstPayload)
        .putString(first, UTF_8.newEncoder())
        // continuation frame
        .put((byte) 0x00)
        .put((byte) secondPayload)
        .putString(second, UTF_8.newEncoder())
        // ping frame
        .put((byte) 0x89)
        .put((byte) 0x00)
        // continuation frame with FIN
        .put((byte) 0x80)
        .put((byte) thirdPayload)
        .putString(third, UTF_8.newEncoder())
        // binary frame
        .put((byte) 0x82)
        .put((byte) fourthPayload)
        .put(fourth)
        .flip();
  }
  @Test
  public void pingInBinaryContinuationSequence() throws Exception {
    ProtocolCodecSessionEx session = new ProtocolCodecSessionEx();
    IoBufferAllocatorEx<?> allocator = session.getBufferAllocator();
    ProtocolDecoder decoder = new WsFrameDecoder(allocator, 400);

    int firstPayload = 125;
    byte[] first = createString('a', firstPayload).getBytes("UTF-8");

    int secondPayload = 125;
    byte[] second = createString('b', secondPayload).getBytes("UTF-8");

    int thirdPayload = 4;
    byte[] third = createString('c', thirdPayload).getBytes("UTF-8");

    int fourthPayload = 6;
    String fourth = createString('d', fourthPayload);

    IoBufferEx in =
        allocator
            .wrap(
                allocator.allocate(
                    firstPayload + secondPayload + 2 + thirdPayload + fourthPayload + 8))
            // text frame
            .put((byte) 0x01)
            .put((byte) firstPayload)
            .put(first)
            // continuation frame
            .put((byte) 0x00)
            .put((byte) secondPayload)
            .put(second)
            // ping frame
            .put((byte) 0x89)
            .put((byte) 0x00)
            // continuation frame with FIN
            .put((byte) 0x80)
            .put((byte) thirdPayload)
            .put(third)
            // binary frame
            .put((byte) 0x82)
            .put((byte) fourthPayload)
            .putString(fourth, UTF_8.newEncoder())
            .flip();

    decoder.decode(session, (IoBuffer) in, session.getDecoderOutput());

    WsMessage out1 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsTextMessage(allocator.wrap(ByteBuffer.wrap(first)), false), out1);

    WsMessage out2 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsContinuationMessage(allocator.wrap(ByteBuffer.wrap(second)), false), out2);

    WsMessage out = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsPingMessage(allocator.wrap(allocator.allocate(0))), out);

    WsMessage out3 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(new WsContinuationMessage(allocator.wrap(ByteBuffer.wrap(third))), out3);

    WsMessage out4 = (WsMessage) session.getDecoderOutputQueue().poll();
    assertEquals(
        new WsBinaryMessage(allocator.wrap(ByteBuffer.wrap(fourth.getBytes(UTF_8)))), out4);

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    decoder.finishDecode(session, session.getDecoderOutput());

    assertTrue(session.getDecoderOutputQueue().isEmpty());
    assertFalse(in.hasRemaining());
  }