package net.glowstone.net.pipeline;

import com.flowpowered.network.Message;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.concurrent.atomic.AtomicReference;
import net.glowstone.net.GameServer;
import net.glowstone.net.GlowSession;

/**
 * Experimental pipeline component, based on flow-net's MessageHandler.
 */
public final class MessageHandler extends SimpleChannelInboundHandler<Message> {

    /**
     * The associated session
     */
    private final AtomicReference<GlowSession> session = new AtomicReference<>(null);
    private final GameServer connectionManager;

    /**
     * Creates a new network event handler.
     *
     * @param connectionManager The connection manager to manage connections for this message handler.
     */
    public MessageHandler(GameServer connectionManager) {
        this.connectionManager = connectionManager;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        Channel c = ctx.channel();
        GlowSession 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.get().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) {
            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);
    }

    public AtomicReference<GlowSession> getSession() {
        return session;
    }
}

package net.glowstone.net.pipeline;

import com.flowpowered.network.Message;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.concurrent.atomic.AtomicReference;
import net.glowstone.net.GameServer;
import net.glowstone.net.GlowSession;

/**
 * Experimental pipeline component, based on flow-net's MessageHandler.
 */
public final class MessageHandler extends SimpleChannelInboundHandler<Message> {

    /**
     * The associated session.
     */
    private final AtomicReference<GlowSession> session = new AtomicReference<>(null);
    private final GameServer connectionManager;

    /**
     * Creates a new network event handler.
     *
     * @param connectionManager The connection manager to manage connections for this message
     *         handler.
     */
    public MessageHandler(GameServer connectionManager) {
        this.connectionManager = connectionManager;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        Channel c = ctx.channel();
        GlowSession 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.get().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) {
            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);
    }

    public AtomicReference<GlowSession> getSession() {
        return session;
    }
}

Fix CheckStyle issues in net/pipeline/MessageHandler.java (#668)