package com.asteria.net.login; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import java.security.SecureRandom; import java.util.List; import com.asteria.game.character.player.IOState; import com.asteria.net.NetworkConstants; import com.asteria.net.PlayerIO; /** * The {@link ByteToMessageDecoder} implementation that will manage the * handshake section of the login protocol. * * @author lare96 <http://github.com/lare96> */ public final class LoginHandshakeHandler extends ByteToMessageDecoder { /** * A secure random number generator, will create session keys for clients. */ private static final SecureRandom RANDOM = new SecureRandom(); @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { // Read the initial request value, validate it. if (in.readableBytes() < 2) return; int request = in.readUnsignedByte(); in.readByte(); if (request != 14) throw new Exception("Invalid login request [" + request + "]"); // Write and send the response to the request. ByteBuf buf = Unpooled.buffer(17); buf.writeLong(0); buf.writeByte(0); buf.writeLong(RANDOM.nextLong()); ctx.channel().writeAndFlush(buf); // Reconfigure the pipeline and session state for the next login stage. PlayerIO session = ctx.channel().attr(NetworkConstants.SESSION_KEY).get(); session.setState(IOState.LOGGING_IN); ctx.pipeline().addAfter("login-handshake", "post-login-handshake", new PostLoginHandshakeHandler()); ctx.pipeline().remove(this); } }