package net.minecraftforkage.internal; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.TimeUnit; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.HashedWheelTimer; import io.netty.util.Timeout; import io.netty.util.Timer; import io.netty.util.TimerTask; /** * Delays all incoming packets by a fixed time period. Somewhat hacky, but * only used for testing anyway. * * @author immibis */ public class FakeLatencyHandler extends ChannelInboundHandlerAdapter { private static final Timer timer = new HashedWheelTimer(); public static final int LATENCY_MS; static { Integer i = Integer.getInteger("net.mcforkage.fakeLatency"); LATENCY_MS = (i == null ? 0 : i.intValue()); } private abstract static class Task implements TimerTask { @Override public final void run(Timeout arg0) throws Exception { synchronized(tasks) { tasks.poll().actuallyRun(); } } abstract void actuallyRun(); } private void addTask(Task task) { synchronized(tasks) { tasks.add(task); } timer.newTimeout(task, LATENCY_MS, TimeUnit.MILLISECONDS); } private static final Queue<Task> tasks = new LinkedList<Task>(); @Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { addTask(new Task() { @Override void actuallyRun() { ctx.fireChannelRead(msg); } }); } @Override public void channelReadComplete(final ChannelHandlerContext ctx) throws Exception { addTask(new Task() { @Override void actuallyRun() { ctx.fireChannelReadComplete(); } }); } @Override public void channelActive(final ChannelHandlerContext ctx) throws Exception { // Don't delay this ctx.fireChannelActive(); } @Override public void channelInactive(final ChannelHandlerContext ctx) throws Exception { addTask(new Task() { @Override void actuallyRun() { ctx.fireChannelInactive(); } }); } public static boolean isEnabled() { return System.getProperty("net.mcforkage.fakeLatency") != null; } }