@Override public List<MessagePart> sendMessagePart(List<MessagePart> uncompressedParts) { List<MessagePart> allCompressedParts = new ArrayList<MessagePart>(); for (MessagePart uncompressedPart : uncompressedParts) { byte opCode = uncompressedPart.getOpCode(); if (Util.isControl(opCode)) { // Control messages can appear in the middle of other messages // and must not be compressed. Pass it straight through allCompressedParts.add(uncompressedPart); } else { List<MessagePart> compressedParts = new ArrayList<MessagePart>(); ByteBuffer uncompressedPayload = uncompressedPart.getPayload(); SendHandler uncompressedIntermediateHandler = uncompressedPart.getIntermediateHandler(); deflater.setInput( uncompressedPayload.array(), uncompressedPayload.arrayOffset() + uncompressedPayload.position(), uncompressedPayload.remaining()); int flush = (uncompressedPart.isFin() ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH); boolean deflateRequired = true; while (deflateRequired) { ByteBuffer compressedPayload = writeBuffer; int written = deflater.deflate( compressedPayload.array(), compressedPayload.arrayOffset() + compressedPayload.position(), compressedPayload.remaining(), flush); compressedPayload.position(compressedPayload.position() + written); if (!uncompressedPart.isFin() && compressedPayload.hasRemaining() && deflater.needsInput()) { // This message part has been fully processed by the // deflater. Fire the send handler for this message part // and move on to the next message part. break; } // If this point is reached, a new compressed message part // will be created... MessagePart compressedPart; // .. and a new writeBuffer will be required. writeBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE); // Flip the compressed payload ready for writing compressedPayload.flip(); boolean fin = uncompressedPart.isFin(); boolean full = compressedPayload.limit() == compressedPayload.capacity(); boolean needsInput = deflater.needsInput(); if (fin && !full && needsInput) { // End of compressed message. Drop EOM bytes and output. compressedPayload.limit(compressedPayload.limit() - EOM_BYTES.length); compressedPart = new MessagePart( true, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); deflateRequired = false; startNewMessage(); } else if (full && !needsInput) { // Write buffer full and input message not fully read. // Output and start new compressed part. compressedPart = new MessagePart( false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); } else if (!fin && full && needsInput) { // Write buffer full and input message not fully read. // Output and get more data. compressedPart = new MessagePart( false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); deflateRequired = false; } else if (fin && full && needsInput) { // Write buffer full. Input fully read. Deflater may be // in one of four states: // - output complete (just happened to align with end of // buffer // - in middle of EOM bytes // - about to write EOM bytes // - more data to write int eomBufferWritten = deflater.deflate(EOM_BUFFER, 0, EOM_BUFFER.length, Deflater.SYNC_FLUSH); if (eomBufferWritten < EOM_BUFFER.length) { // EOM has just been completed compressedPayload.limit( compressedPayload.limit() - EOM_BYTES.length + eomBufferWritten); compressedPart = new MessagePart( true, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); deflateRequired = false; startNewMessage(); } else { // More data to write // Copy bytes to new write buffer writeBuffer.put(EOM_BUFFER, 0, eomBufferWritten); compressedPart = new MessagePart( false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); } } else { throw new IllegalStateException("Should never happen"); } // Add the newly created compressed part to the set of parts // to pass on to the next transformation. compressedParts.add(compressedPart); } SendHandler uncompressedEndHandler = uncompressedPart.getEndHandler(); int size = compressedParts.size(); if (size > 0) { compressedParts.get(size - 1).setEndHandler(uncompressedEndHandler); } allCompressedParts.addAll(compressedParts); } } if (next == null) { return allCompressedParts; } else { return next.sendMessagePart(allCompressedParts); } }