package net.glowstone.net.pipeline; import com.flowpowered.networking.ConnectionManager; import com.flowpowered.networking.Message; import com.flowpowered.networking.session.Session; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.IdleStateEvent; import net.glowstone.net.GlowSession; import java.util.concurrent.atomic.AtomicReference; /** * Experimental pipeline component, based on flow-net's MessageHandler. */ public final class MessageHandler extends SimpleChannelInboundHandler<Message> { /** * The associated session */ private final AtomicReference<Session> session = new AtomicReference<>(null); private final ConnectionManager connectionManager; /** * Creates a new network event handler. */ public MessageHandler(ConnectionManager connectionManager) { this.connectionManager = connectionManager; } @Override public void channelActive(ChannelHandlerContext ctx) { final Channel c = ctx.channel(); Session s = connectionManager.newSession(c); if (!session.compareAndSet(null, s)) { throw new IllegalStateException("Session may not be set more than once"); } s.onReady(); } @Override public void channelInactive(ChannelHandlerContext ctx) { Session session = this.session.get(); session.onDisconnect(); } @Override protected void channelRead0(ChannelHandlerContext ctx, Message i) { session.get().messageReceived(i); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { ((GlowSession) session.get()).idle(); // todo: find a more elegant way to do this in the future } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { session.get().onInboundThrowable(cause); } }