public void wrapBuffer()

in src/main/java/com/microsoft/azure/proton/transport/ws/impl/WebSocketHandlerImpl.java [88:167]


    public void wrapBuffer(ByteBuffer srcBuffer, ByteBuffer dstBuffer) {
        if ((srcBuffer == null) || (dstBuffer == null)) {
            throw new IllegalArgumentException("input parameter is null");
        }

        if (srcBuffer.remaining() > 0) {
            // We always send masked data
            // RFC: "client MUST mask all frames that it sends to the server"
            final byte[] maskingKey = createRandomMaskingKey();

            // Get data length
            final int dataLength = srcBuffer.remaining();

            // Auto growing buffer for the WS frame, initialized to minimum size
            ByteArrayOutputStream webSocketFrame = new ByteArrayOutputStream(WebSocketHeader.MIN_HEADER_LENGTH_MASKED + dataLength);

            // Create the first byte
            // We always send final WebSocket frame
            // We always send binary message (AMQP)
            byte firstByte = (byte) (WebSocketHeader.FINBIT_MASK | WebSocketHeader.OPCODE_BINARY);
            webSocketFrame.write(firstByte);

            // Create the second byte
            // RFC: "client MUST mask all frames that it sends to the server"
            byte secondByte = WebSocketHeader.MASKBIT_MASK;

            // RFC: The length of the "Payload data", in bytes: if 0-125, that is the payload length.
            if (dataLength <= WebSocketHeader.PAYLOAD_SHORT_MAX) {
                secondByte = (byte) (secondByte | dataLength);
                webSocketFrame.write(secondByte);
            } else if (dataLength <= WebSocketHeader.PAYLOAD_MEDIUM_MAX) {
                // RFC: If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length
                // Create payload byte
                secondByte = (byte) (secondByte | WebSocketHeader.PAYLOAD_EXTENDED_16);
                webSocketFrame.write(secondByte);

                // Create extended length bytes
                webSocketFrame.write((byte) (dataLength >>> 8));
                webSocketFrame.write((byte) (dataLength));
            } else {
                // RFC: If 127, the following 8 bytes interpreted as a 64-bit unsigned integer
                // (the most significant bit MUST be 0) are the payload length.
                // No need for "else if" because if it is longer than what 8 byte length can hold... all bets are off anyway
                secondByte = (byte) (secondByte | WebSocketHeader.PAYLOAD_EXTENDED_64);
                webSocketFrame.write(secondByte);

                webSocketFrame.write((byte) (dataLength >>> 56));
                webSocketFrame.write((byte) (dataLength >>> 48));
                webSocketFrame.write((byte) (dataLength >>> 40));
                webSocketFrame.write((byte) (dataLength >>> 32));
                webSocketFrame.write((byte) (dataLength >>> 24));
                webSocketFrame.write((byte) (dataLength >>> 16));
                webSocketFrame.write((byte) (dataLength >>> 8));
                webSocketFrame.write((byte) (dataLength));
            }

            // Write mask
            webSocketFrame.write(maskingKey[0]);
            webSocketFrame.write(maskingKey[1]);
            webSocketFrame.write(maskingKey[2]);
            webSocketFrame.write(maskingKey[3]);

            // Write masked data
            for (int i = 0; i < dataLength; i++) {
                byte nextByte = srcBuffer.get();
                nextByte ^= maskingKey[i % 4];
                webSocketFrame.write(nextByte);
            }

            // Copy frame to destination buffer
            dstBuffer.clear();
            if (dstBuffer.capacity() >= webSocketFrame.size()) {
                dstBuffer.put(webSocketFrame.toByteArray());
            } else {
                throw new OutOfMemoryError("insufficient output buffer size");
            }
        } else {
            dstBuffer.clear();
        }
    }