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 net.glowstone.net.GameServer;
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<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;
}
}