package lilypad.server.connect.node; import java.io.IOException; import lilypad.packet.common.Packet; import lilypad.packet.connect.impl.KeepalivePacket; import lilypad.packet.connect.impl.RequestPacket; import lilypad.server.common.IAuthenticator; import lilypad.server.common.IPlayable; import lilypad.server.connect.ConnectService; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.ReadTimeoutException; import io.netty.util.AttributeKey; @Sharable public class NodeHandler extends SimpleChannelInboundHandler<Packet> { private static final AttributeKey<NodeSession> nodeSession = new AttributeKey<NodeSession>("nodeSession"); private ConnectService connectService; private IAuthenticator authenticator; private IPlayable playable; public NodeHandler(ConnectService connectService, IAuthenticator authenticator, IPlayable playable) { this.connectService = connectService; this.authenticator = authenticator; this.playable = playable; } @Override public void channelActive(ChannelHandlerContext context) throws Exception { context.attr(nodeSession).setIfAbsent(new NodeSession(context.channel(), this.connectService, this.authenticator, this.playable)); } @Override public void channelInactive(ChannelHandlerContext context) throws Exception { context.attr(nodeSession).getAndSet(null).cleanup(); } @Override protected void channelRead0(ChannelHandlerContext context, Packet packet) throws Exception { switch(packet.getOpcode()) { case 0x00: KeepalivePacket keepalivePacket = (KeepalivePacket) packet; context.attr(nodeSession).get().pong(keepalivePacket.getRandom()); break; case 0x01: context.attr(nodeSession).get().handleRequest((RequestPacket) packet); break; default: context.close(); // invalid packet break; } } @Override public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception { Channel channel = context.channel(); if(cause instanceof IOException) { if(!cause.getMessage().equals("Connection reset by peer")) { cause.printStackTrace(); } } else if (!(cause instanceof ReadTimeoutException)) { cause.printStackTrace(); } if(channel.isOpen()) { channel.close(); } } }