Beispiel #1
0
  @Override
  public TransformationResult getMoreData(byte opCode, boolean fin, int rsv, ByteBuffer dest)
      throws IOException {
    // Control frames are never compressed and may appear in the middle of
    // a WebSocket method. Pass them straight through.
    if (Util.isControl(opCode)) {
      return next.getMoreData(opCode, fin, rsv, dest);
    }

    if (!Util.isContinuation(opCode)) {
      // First frame in new message
      skipDecompression = (rsv & RSV_BITMASK) == 0;
    }

    // Pass uncompressed frames straight through.
    if (skipDecompression) {
      return next.getMoreData(opCode, fin, rsv, dest);
    }

    int written;
    boolean usedEomBytes = false;

    while (dest.remaining() > 0) {
      // Space available in destination. Try and fill it.
      try {
        written =
            inflater.inflate(dest.array(), dest.arrayOffset() + dest.position(), dest.remaining());
      } catch (DataFormatException e) {
        throw new IOException(sm.getString("perMessageDeflate.deflateFailed"), e);
      }
      dest.position(dest.position() + written);

      if (inflater.needsInput() && !usedEomBytes) {
        if (dest.hasRemaining()) {
          readBuffer.clear();
          TransformationResult nextResult =
              next.getMoreData(opCode, fin, (rsv ^ RSV_BITMASK), readBuffer);
          inflater.setInput(readBuffer.array(), readBuffer.arrayOffset(), readBuffer.position());
          if (TransformationResult.UNDERFLOW.equals(nextResult)) {
            return nextResult;
          } else if (TransformationResult.END_OF_FRAME.equals(nextResult)
              && readBuffer.position() == 0) {
            if (fin) {
              inflater.setInput(EOM_BYTES);
              usedEomBytes = true;
            } else {
              return TransformationResult.END_OF_FRAME;
            }
          }
        }
      } else if (written == 0) {
        if (fin && (isServer && !clientContextTakeover || !isServer && !serverContextTakeover)) {
          inflater.reset();
        }
        return TransformationResult.END_OF_FRAME;
      }
    }

    return TransformationResult.OVERFLOW;
  }
Beispiel #2
0
  private boolean processDataBinary() throws IOException {
    // Copy the available data to the buffer
    TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
    while (!TransformationResult.END_OF_FRAME.equals(tr)) {
      // Frame not complete - what did we run out of?
      if (TransformationResult.UNDERFLOW.equals(tr)) {
        // Ran out of input data - get some more
        return false;
      }

      // Ran out of message buffer - flush it
      if (!usePartial()) {
        CloseReason cr =
            new CloseReason(
                CloseCodes.TOO_BIG,
                sm.getString(
                    "wsFrame.bufferTooSmall",
                    Integer.valueOf(messageBufferBinary.capacity()),
                    Long.valueOf(payloadLength)));
        throw new WsIOException(cr);
      }
      messageBufferBinary.flip();
      ByteBuffer copy = ByteBuffer.allocate(messageBufferBinary.limit());
      copy.put(messageBufferBinary);
      copy.flip();
      sendMessageBinary(copy, false);
      messageBufferBinary.clear();
      // Read more data
      tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
    }

    // Frame is fully received
    // Send the message if either:
    // - partial messages are supported
    // - the message is complete
    if (usePartial() || !continuationExpected) {
      messageBufferBinary.flip();
      ByteBuffer copy = ByteBuffer.allocate(messageBufferBinary.limit());
      copy.put(messageBufferBinary);
      copy.flip();
      sendMessageBinary(copy, !continuationExpected);
      messageBufferBinary.clear();
    }

    if (continuationExpected) {
      // More data for this message expected, start a new frame
      newFrame();
    } else {
      // Message is complete, start a new message
      newMessage();
    }

    return true;
  }
Beispiel #3
0
  private boolean processDataText() throws IOException {
    // Copy the available data to the buffer
    TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
    while (!TransformationResult.END_OF_FRAME.equals(tr)) {
      // Frame not complete - we ran out of something
      // Convert bytes to UTF-8
      messageBufferBinary.flip();
      while (true) {
        CoderResult cr = utf8DecoderMessage.decode(messageBufferBinary, messageBufferText, false);
        if (cr.isError()) {
          throw new WsIOException(
              new CloseReason(CloseCodes.NOT_CONSISTENT, sm.getString("wsFrame.invalidUtf8")));
        } else if (cr.isOverflow()) {
          // Ran out of space in text buffer - flush it
          if (usePartial()) {
            messageBufferText.flip();
            sendMessageText(false);
            messageBufferText.clear();
          } else {
            throw new WsIOException(
                new CloseReason(CloseCodes.TOO_BIG, sm.getString("wsFrame.textMessageTooBig")));
          }
        } else if (cr.isUnderflow()) {
          // Compact what we have to create as much space as possible
          messageBufferBinary.compact();

          // Need more input
          // What did we run out of?
          if (TransformationResult.OVERFLOW.equals(tr)) {
            // Ran out of message buffer - exit inner loop and
            // refill
            break;
          } else {
            // TransformationResult.UNDERFLOW
            // Ran out of input data - get some more
            return false;
          }
        }
      }
      // Read more input data
      tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
    }

    messageBufferBinary.flip();
    boolean last = false;
    // Frame is fully received
    // Convert bytes to UTF-8
    while (true) {
      CoderResult cr = utf8DecoderMessage.decode(messageBufferBinary, messageBufferText, last);
      if (cr.isError()) {
        throw new WsIOException(
            new CloseReason(CloseCodes.NOT_CONSISTENT, sm.getString("wsFrame.invalidUtf8")));
      } else if (cr.isOverflow()) {
        // Ran out of space in text buffer - flush it
        if (usePartial()) {
          messageBufferText.flip();
          sendMessageText(false);
          messageBufferText.clear();
        } else {
          throw new WsIOException(
              new CloseReason(CloseCodes.TOO_BIG, sm.getString("wsFrame.textMessageTooBig")));
        }
      } else if (cr.isUnderflow() & !last) {
        // End of frame and possible message as well.

        if (continuationExpected) {
          // If partial messages are supported, send what we have
          // managed to decode
          if (usePartial()) {
            messageBufferText.flip();
            sendMessageText(false);
            messageBufferText.clear();
          }
          messageBufferBinary.compact();
          newFrame();
          // Process next frame
          return true;
        } else {
          // Make sure coder has flushed all output
          last = true;
        }
      } else {
        // End of message
        messageBufferText.flip();
        sendMessageText(true);

        newMessage();
        return true;
      }
    }
  }