package net.scapeemulator.game.net.handshake; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundByteHandlerAdapter; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import java.io.IOException; import java.nio.charset.StandardCharsets; import net.scapeemulator.game.net.auto.AutoLoginDecoder; import net.scapeemulator.game.net.jaggrab.JaggrabDecoder; import net.scapeemulator.game.net.jaggrab.JaggrabEncoder; import net.scapeemulator.game.net.login.LoginDecoder; import net.scapeemulator.game.net.login.LoginEncoder; import net.scapeemulator.game.net.register.RegisterDecoder; import net.scapeemulator.game.net.register.RegisterEncoder; import net.scapeemulator.game.net.update.FileResponseEncoder; import net.scapeemulator.game.net.update.UpdateDecoder; import net.scapeemulator.game.net.update.UpdateStatusMessageEncoder; import net.scapeemulator.game.net.update.XorEncoder; import net.scapeemulator.game.net.world.WorldListDecoder; import net.scapeemulator.game.net.world.WorldListEncoder; public final class HandshakeDecoder extends ChannelInboundByteHandlerAdapter { @Override public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf buf) throws IOException { if (!buf.isReadable()) return; int service = buf.readUnsignedByte(); ByteBuf additionalBuf = null; if (buf.isReadable()) { additionalBuf = buf.readBytes(buf.readableBytes()); } ChannelPipeline pipeline = ctx.pipeline(); pipeline.remove(HandshakeDecoder.class); switch (service) { case HandshakeMessage.SERVICE_LOGIN: pipeline.addFirst( new LoginEncoder(), new LoginDecoder()); break; case HandshakeMessage.SERVICE_UPDATE: pipeline.addFirst( new FileResponseEncoder(), new UpdateStatusMessageEncoder(), new XorEncoder(), new UpdateDecoder()); break; case HandshakeMessage.SERVICE_JAGGRAB: pipeline.addFirst( new JaggrabEncoder(), // Dummy encoder here because it wasn't working for some reason without it new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()), new StringDecoder(StandardCharsets.US_ASCII), new JaggrabDecoder()); break; case HandshakeMessage.SERVICE_REGISTER_PERSONAL_DETAILS: case HandshakeMessage.SERVICE_REGISTER_USERNAME: case HandshakeMessage.SERVICE_REGISTER_COMMIT: pipeline.addFirst( new RegisterEncoder(), new RegisterDecoder(service)); break; case HandshakeMessage.SERVICE_AUTO_LOGIN: pipeline.addFirst( new LoginEncoder(), new AutoLoginDecoder()); break; case HandshakeMessage.SERVICE_WORLD_LIST: pipeline.addFirst( new WorldListEncoder(), new WorldListDecoder()); break; default: throw new IOException("Invalid service id: " + service + "."); } ctx.nextInboundMessageBuffer().add(new HandshakeMessage(service)); ctx.fireInboundBufferUpdated(); if (additionalBuf != null) { ChannelHandlerContext head = ctx.pipeline().firstContext(); head.nextInboundByteBuffer().writeBytes(additionalBuf); head.fireInboundBufferUpdated(); } } }