예제 #1
0
  @Test
  public void testParse65536ByteBinaryCase1_2_7() {
    int length = 65536;

    ByteBuffer expected = ByteBuffer.allocate(length + 11);

    expected.put(new byte[] {(byte) 0x82});
    byte b = 0x00; // no masking
    b |= 0x7F;
    expected.put(b);
    expected.put(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});

    for (int i = 0; i < length; ++i) {
      expected.put("*".getBytes());
    }

    expected.flip();

    WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
    policy.setMaxMessageSize(length);
    Parser parser = new UnitParser(policy);
    IncomingFramesCapture capture = new IncomingFramesCapture();
    parser.setIncomingFramesHandler(capture);
    parser.parse(expected);

    capture.assertNoErrors();
    capture.assertHasFrame(OpCode.BINARY, 1);

    Frame pActual = capture.getFrames().get(0);
    Assert.assertThat("BinaryFrame.payloadLength", pActual.getPayloadLength(), is(length));
    // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
  }
예제 #2
0
  @Test
  public void testParse128ByteBinaryCase1_2_5() {
    int length = 128;

    ByteBuffer expected = ByteBuffer.allocate(length + 5);

    expected.put(new byte[] {(byte) 0x82});
    byte b = 0x00; // no masking
    b |= 0x7E;
    expected.put(b);
    expected.putShort((short) length);

    for (int i = 0; i < length; ++i) {
      expected.put("*".getBytes());
    }

    expected.flip();

    Parser parser = new UnitParser(policy);
    IncomingFramesCapture capture = new IncomingFramesCapture();
    parser.setIncomingFramesHandler(capture);
    parser.parse(expected);

    capture.assertNoErrors();
    capture.assertHasFrame(OpCode.BINARY, 1);

    Frame pActual = capture.getFrames().get(0);
    Assert.assertThat("BinaryFrame.payloadLength", pActual.getPayloadLength(), is(length));
    // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
  }
 @OnWebSocketFrame
 public void onWebSocketFrame(Frame frame) {
   if (OpCode.PONG == frame.getOpCode()) {
     ByteBuffer payload = frame.getPayload() != null ? frame.getPayload() : EMPTY_PAYLOAD;
     PongMessage message = new PongMessage(payload);
     try {
       this.webSocketHandler.handleMessage(this.wsSession, message);
     } catch (Throwable t) {
       ExceptionWebSocketHandlerDecorator.tryCloseWithError(this.wsSession, t, logger);
     }
   }
 }
예제 #4
0
  @Override
  public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) {
    ByteBuffer payload = frame.getPayload();
    int length = payload != null ? payload.remaining() : 0;
    if (OpCode.isControlFrame(frame.getOpCode()) || maxLength <= 0 || length <= maxLength) {
      nextOutgoingFrame(frame, callback, batchMode);
      return;
    }

    FrameEntry entry = new FrameEntry(frame, callback, batchMode);
    if (LOG.isDebugEnabled()) LOG.debug("Queuing {}", entry);
    entries.offer(entry);
    flusher.iterate();
  }
예제 #5
0
 /**
  * Construct new DataFrame based on headers of provided frame, overriding for continuations if
  * needed.
  *
  * <p>Useful for when working in extensions and a new frame needs to be created.
  */
 public DataFrame(Frame basedOn, boolean continuation) {
   super(basedOn.getOpCode());
   copyHeaders(basedOn);
   if (continuation) {
     setOpCode(OpCode.CONTINUATION);
   }
 }
 @Override
 protected void nextOutgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) {
   if (frame.isFin() && !outgoingContextTakeover) {
     LOG.debug("Outgoing Context Reset");
     getDeflater().reset();
   }
   super.nextOutgoingFrame(frame, callback, batchMode);
 }
 @Override
 protected void nextIncomingFrame(Frame frame) {
   if (frame.isFin() && !incomingContextTakeover) {
     LOG.debug("Incoming Context Reset");
     getInflater().reset();
   }
   super.nextIncomingFrame(frame);
 }
  @Override
  public void incomingFrame(Frame frame) {
    // Incoming frames are always non concurrent because
    // they are read and parsed with a single thread, and
    // therefore there is no need for synchronization.

    // This extension requires the RSV1 bit set only in the first frame.
    // Subsequent continuation frames don't have RSV1 set, but are compressed.
    if (frame.getType().isData()) incomingCompressed = frame.isRsv1();

    if (OpCode.isControlFrame(frame.getOpCode()) || !frame.hasPayload() || !incomingCompressed) {
      nextIncomingFrame(frame);
      return;
    }

    boolean appendTail = frame.isFin();
    ByteBuffer payload = frame.getPayload();
    int remaining = payload.remaining();
    byte[] input = new byte[remaining + (appendTail ? TAIL_BYTES.length : 0)];
    payload.get(input, 0, remaining);
    if (appendTail) System.arraycopy(TAIL_BYTES, 0, input, remaining, TAIL_BYTES.length);

    forwardIncoming(frame, decompress(input));

    if (frame.isFin()) incomingCompressed = false;
  }
예제 #9
0
  @Test
  public void testParseEmptyBinaryCase1_2_1() {

    ByteBuffer expected = ByteBuffer.allocate(5);

    expected.put(new byte[] {(byte) 0x82, (byte) 0x00});

    expected.flip();

    Parser parser = new UnitParser(policy);
    IncomingFramesCapture capture = new IncomingFramesCapture();
    parser.setIncomingFramesHandler(capture);
    parser.parse(expected);

    capture.assertNoErrors();
    capture.assertHasFrame(OpCode.BINARY, 1);

    Frame pActual = capture.getFrames().get(0);
    Assert.assertThat("BinaryFrame.payloadLength", pActual.getPayloadLength(), is(0));
    // Assert.assertNull("BinaryFrame.payload",pActual.getPayloadData());
  }
예제 #10
0
    private void fragment(FrameEntry entry, boolean first) {
      Frame frame = entry.frame;
      ByteBuffer payload = frame.getPayload();
      int remaining = payload.remaining();
      int length = Math.min(remaining, maxLength);
      finished = length == remaining;

      boolean continuation = frame.getType().isContinuation() || !first;
      DataFrame fragment = new DataFrame(frame, continuation);
      boolean fin = frame.isFin() && finished;
      fragment.setFin(fin);

      int limit = payload.limit();
      int newLimit = payload.position() + length;
      payload.limit(newLimit);
      ByteBuffer payloadFragment = payload.slice();
      payload.limit(limit);
      fragment.setPayload(payloadFragment);
      if (LOG.isDebugEnabled()) LOG.debug("Fragmented {}->{}", frame, fragment);
      payload.position(newLimit);

      nextOutgoingFrame(fragment, this, entry.batchMode);
    }
예제 #11
0
  public void enqueue(Frame frame, WriteCallback callback, BatchMode batchMode) {
    if (closed.get()) {
      notifyCallbackFailure(callback, new EOFException("Connection has been closed locally"));
      return;
    }
    if (flusher.isFailed()) {
      notifyCallbackFailure(callback, failure);
      return;
    }

    FrameEntry entry = new FrameEntry(frame, callback, batchMode);

    synchronized (lock) {
      switch (frame.getOpCode()) {
        case OpCode.PING:
          {
            // Prepend PINGs so they are processed first.
            queue.add(0, entry);
            break;
          }
        case OpCode.CLOSE:
          {
            // There may be a chance that other frames are
            // added after this close frame, but we will
            // fail them later to keep it simple here.
            closed.set(true);
            queue.add(entry);
            break;
          }
        default:
          {
            queue.add(entry);
            break;
          }
      }
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug("{} queued {}", this, entry);
    }

    flusher.iterate();
  }
  @Override
  public void incomingFrame(Frame frame) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("{}.onFrame({})", websocket.getClass().getSimpleName(), frame);
    }

    try {
      onFrame(frame);

      byte opcode = frame.getOpCode();
      switch (opcode) {
        case OpCode.CLOSE:
          {
            boolean validate = true;
            CloseFrame closeframe = (CloseFrame) frame;
            CloseInfo close = new CloseInfo(closeframe, validate);

            // notify user websocket pojo
            onClose(close);

            // process handshake
            session.getConnection().getIOState().onCloseRemote(close);

            return;
          }
        case OpCode.PING:
          {
            if (LOG.isDebugEnabled()) {
              LOG.debug("PING: {}", BufferUtil.toDetailString(frame.getPayload()));
            }
            ByteBuffer pongBuf;
            if (frame.hasPayload()) {
              pongBuf = ByteBuffer.allocate(frame.getPayload().remaining());
              BufferUtil.put(frame.getPayload().slice(), pongBuf);
              BufferUtil.flipToFlush(pongBuf, 0);
            } else {
              pongBuf = ByteBuffer.allocate(0);
            }
            onPing(frame.getPayload());
            session.getRemote().sendPong(pongBuf);
            break;
          }
        case OpCode.PONG:
          {
            if (LOG.isDebugEnabled()) {
              LOG.debug("PONG: {}", BufferUtil.toDetailString(frame.getPayload()));
            }
            onPong(frame.getPayload());
            break;
          }
        case OpCode.BINARY:
          {
            onBinaryFrame(frame.getPayload(), frame.isFin());
            return;
          }
        case OpCode.TEXT:
          {
            onTextFrame(frame.getPayload(), frame.isFin());
            return;
          }
        case OpCode.CONTINUATION:
          {
            onContinuationFrame(frame.getPayload(), frame.isFin());
            return;
          }
        default:
          {
            LOG.debug("Unhandled OpCode: {}", opcode);
          }
      }
    } catch (NotUtf8Exception e) {
      terminateConnection(StatusCode.BAD_PAYLOAD, e.getMessage());
    } catch (CloseException e) {
      terminateConnection(e.getStatusCode(), e.getMessage());
    } catch (Throwable t) {
      unhandled(t);
    }
  }
예제 #13
0
 @Override
 public String toString() {
   return frame.toString();
 }