package net.scapeemulator.game.net.login; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelPipeline; import io.netty.handler.timeout.ReadTimeoutHandler; import java.io.IOException; import java.security.SecureRandom; import net.burtleburtle.bob.rand.IsaacRandom; import net.scapeemulator.cache.ChecksumTable; import net.scapeemulator.game.GameServer; import net.scapeemulator.game.model.player.interfaces.InterfaceSet.DisplayMode; import net.scapeemulator.game.model.player.Player; import net.scapeemulator.game.net.RsChannelHandler; import net.scapeemulator.game.net.Session; import net.scapeemulator.game.net.game.GameFrameDecoder; import net.scapeemulator.game.net.game.GameFrameEncoder; import net.scapeemulator.game.net.game.GameMessageDecoder; import net.scapeemulator.game.net.game.GameMessageEncoder; import net.scapeemulator.game.net.game.GameSession; public final class LoginSession extends Session { private static final SecureRandom random = new SecureRandom(); private final LoginService service; private final long serverSessionKey = random.nextLong(); private int displayMode; private IsaacRandom inRandom, outRandom; public LoginSession(GameServer server, Channel channel) { super(server, channel); this.service = server.getLoginService(); init(); } private void init() { ByteBuf buf = channel.alloc().buffer(8); buf.writeLong(serverSessionKey); channel.write(new LoginResponse(LoginResponse.STATUS_EXCHANGE_KEYS, buf)); } public void sendLoginFailure(int status) { LoginResponse response = new LoginResponse(status); channel.write(response).addListener(ChannelFutureListener.CLOSE); } public void sendLoginSuccess(int status, final Player player) { ByteBuf buf = channel.alloc().buffer(11); buf.writeByte(player.getRights()); buf.writeByte(0); buf.writeByte(0); buf.writeByte(0); buf.writeByte(0); buf.writeByte(0); buf.writeByte(0); buf.writeShort(player.getId()); buf.writeByte(1); buf.writeByte(1); if (displayMode == 0 || displayMode == 1) { player.getInterfaceSet().setDisplayMode(DisplayMode.FIXED); } else { player.getInterfaceSet().setDisplayMode(DisplayMode.RESIZABLE); } final ChannelPipeline pipeline = channel.pipeline(); final GameSession session = new GameSession(server, channel, player); RsChannelHandler handler = pipeline.get(RsChannelHandler.class); handler.setSession(session); pipeline.remove(ReadTimeoutHandler.class); LoginResponse response = new LoginResponse(status, buf); ChannelFuture future = channel.write(response); future.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) { if (future.isSuccess()) { pipeline.addFirst(new GameFrameEncoder(outRandom), new GameMessageEncoder(server.getCodecRepository()), new GameFrameDecoder(inRandom), new GameMessageDecoder(server.getCodecRepository())); session.init(); } } }); } @Override public void messageReceived(Object message) throws IOException { LoginRequest request = (LoginRequest) message; if (request.getServerSessionKey() != serverSessionKey) throw new IOException("Server session key mismatch."); boolean versionMismatch = false; if (request.getVersion() != server.getVersion()) versionMismatch = true; ChecksumTable table = server.getChecksumTable(); int[] crc = request.getCrc(); for (int i = 0; i < crc.length; i++) { if (table.getEntry(i).getCrc() != crc[i]) { versionMismatch = true; break; } } if (versionMismatch) { sendLoginFailure(LoginResponse.STATUS_GAME_UPDATED); return; } long clientSessionKey = request.getClientSessionKey(); long serverSessionKey = request.getServerSessionKey(); int[] seed = new int[4]; seed[0] = (int) (clientSessionKey >> 32); seed[1] = (int) clientSessionKey; seed[2] = (int) (serverSessionKey >> 32); seed[3] = (int) serverSessionKey; inRandom = new IsaacRandom(seed); for (int i = 0; i < seed.length; i++) seed[i] += 50; outRandom = new IsaacRandom(seed); displayMode = request.getDisplayMode(); service.addLoginRequest(this, request); } }