package net.tomp2p.holep; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import net.tomp2p.connection.Dispatcher; import net.tomp2p.holep.strategy.AbstractHolePStrategy; import net.tomp2p.message.Message; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class is responsible that no duplicate messages are processed by the * peer. Currently it is used in {@link AbstractHolePStrategy} to filter * duplicate messages transmitted by the hole punching procedure. * * @author jonaswagner * */ @Sharable public class DuplicatesHandler extends SimpleChannelInboundHandler<Message> { private static final int POSITION_ZERO = 0; private static final Logger LOG = LoggerFactory.getLogger(DuplicatesHandler.class); private final Dispatcher dispatcher; private volatile int messageId = 0; private volatile boolean first = true; public DuplicatesHandler(final Dispatcher dispatcher) { this.dispatcher = dispatcher; } /** * This method filters all messages out which contain the same messageId as * the first received message with the isExpectDuplicateFlag. */ @Override protected void channelRead0(final ChannelHandlerContext ctx, final Message msg) throws Exception { if (msg.isExpectDuplicate()) { if (first) { first = false; messageId = msg.intAt(POSITION_ZERO); dispatcher.channelRead(ctx, msg); LOG.debug("message with original messageId = " + messageId + " has been received!"); } else if (messageId == msg.intAt(POSITION_ZERO)) { LOG.trace("message with original messageId = " + messageId + " has been ignored!"); ctx.close(); } else { LOG.debug("Message received via hole punching will be forwarded to the Dispatcher!"); dispatcher.channelRead(ctx, msg); } // if some day UDT or some similar code is integrated into tomp2p, // here's where its handler should be placed } else { LOG.debug("Message received via hole punching will be forwarded to the Dispatcher!"); dispatcher.channelRead(ctx, msg); } } }