package com.tacitknowledge.slowlight.proxyserver.handler; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import java.util.concurrent.TimeUnit; /** * This task is used to split given channel message into data fragments and will send them a separate messages to the next handlers. * * @author Alexandr Donciu (adonciu@tacitknowledge.com) */ public class WriteDataFragmentsTask implements Runnable { private ChannelHandlerContext ctx; private ByteBuf msg; private ChannelPromise promise; private int maxDataSize; private long delay; private WriteDataFragmentsTask thisTask; public WriteDataFragmentsTask(final ChannelHandlerContext ctx, final ByteBuf msg, final ChannelPromise promise, final int maxDataSize, final long delay) { this.ctx = ctx; this.msg = msg; this.promise = promise; this.maxDataSize = maxDataSize; this.delay = delay; this.thisTask = this; } @Override public void run() { if (msg.isReadable()) { ctx.writeAndFlush(readDataFragment(msg)).addListener(new WriteDataListener()); } } private ByteBuf readDataFragment(final ByteBuf readChannelBuffer) { final int readableBytes = readChannelBuffer.readableBytes(); final int bytesToRead = maxDataSize == 0 || readableBytes < maxDataSize ? readableBytes : maxDataSize; final ByteBuf writeChannelBuffer = Unpooled.buffer(bytesToRead); readChannelBuffer.readBytes(writeChannelBuffer, bytesToRead); return writeChannelBuffer; } /** * Listener class to schedule next write data fragment task. */ protected class WriteDataListener implements ChannelFutureListener { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (future.isSuccess()) { if (msg.readableBytes() > 0) { ctx.executor().schedule(thisTask, delay, TimeUnit.MILLISECONDS); } else { promise.setSuccess(); } } else { future.channel().close(); } } } }