Advertisement
Guest User

Decoder

a guest
Apr 29th, 2016
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.19 KB | None | 0 0
  1. package org.kainos.rs2.network.gameserver.codec.protocol.login;
  2.  
  3. import java.math.BigInteger;
  4. import java.util.List;
  5.  
  6. import org.kainos.rs2.game.world.visual.Display;
  7. import org.kainos.rs2.network.gameserver.codec.protocol.Protocol;
  8. import org.kainos.rs2.network.gameserver.codec.protocol.login.message.LoginRequestMessage;
  9. import org.kainos.utilities.Utilities;
  10. import org.kainos.utilities.base37.Base37Utils;
  11. import org.kainos.utilities.buffer.BufferUtilities;
  12. import org.kainos.utilities.crypto.BCrypt;
  13. import org.kainos.utilities.crypto.XTEA;
  14. import org.kainos.utilities.isaac.IsaacRandom;
  15.  
  16. import io.netty.buffer.ByteBuf;
  17. import io.netty.buffer.Unpooled;
  18. import io.netty.channel.ChannelHandlerContext;
  19. import io.netty.handler.codec.ByteToMessageDecoder;
  20.  
  21. /**
  22.  * The class that contains the decoding of the entire Login process.
  23.  *
  24.  * @author Waterfiend
  25.  * @date August 11 2015
  26.  */
  27. public class LoginDecoder extends ByteToMessageDecoder {
  28.  
  29.     /**
  30.      * The attempted {@link LoginType}.
  31.      */
  32.     private LoginType loginType;
  33.  
  34.     /**
  35.      * The {@link Display} used during login.
  36.      */
  37.     private Display display;
  38.  
  39.     /*
  40.      * (non-Javadoc)
  41.      *
  42.      * @see io.netty.handler.codec.ByteToMessageDecoder#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf,
  43.      * java.util.List)
  44.      */
  45.     @Override
  46.     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
  47.         if (!in.isReadable()) {
  48.             return;
  49.         }
  50.         int opcode = in.readUnsignedByte(); //The login opcode to read.
  51.         if (opcode != 16 && opcode != 18 && opcode != 19) { //Checks if the opcodes match the following incase of lobby,
  52. // world or even reconnecting to the world
  53.             ctx.channel().close();
  54.             return;
  55.         }
  56.         switch (opcode) {
  57.         case 19:// Lobby
  58.             loginType = LoginType.LOBBY; //The lobby "instance" type of login.
  59.             break;
  60.         case 16:// World
  61.         case 18:// Reconnection of the World
  62.             loginType = LoginType.WORLD; //The actual instance of the world.
  63.             break;
  64.         }
  65.         int length = in.readUnsignedShort(); //The length
  66.         if (in.readableBytes() < length) { //Checks the length
  67.             ctx.channel().close();
  68.             return;
  69.         }
  70.         decodeClientRequest(ctx, in, out); //Performs the decoding request of the client.... Checks if the opcodes match //the login, world & world re-connection [opcodes, etc].
  71.     }
  72.  
  73.     /**
  74.      * Decodes the client request procedure.
  75.      * @param ctx The connected {@link ChannelHandlerContext}.
  76.      * @param in The used {@link ByteBuf}.
  77.      * @param out The used output {@link Object}.
  78.      */
  79.     private void decodeClientRequest(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
  80.         int majorVersion = in.readInt(); //The major version (Server revision - 742) - AKA Cache Version/Revision
  81.         int minorVersion = in.readInt(); //The minor version (Sub revision: 1/any number) AKA Client Version/Revision
  82.         if (majorVersion != Protocol.MAJOR_VERSION || minorVersion != Protocol.MINOR_VERSION) {
  83.             ctx.channel().close();
  84.             return;
  85.         }
  86.         if (loginType.equals(LoginType.WORLD)) { //Checks if the login type matches the world login type to process the //request
  87.             in.readByte();
  88.         }
  89.         decodeLoginRequest(ctx, in, out); //Performs the decoding of the request of login (Checks if the major/minor //versions match the actual ones to load.
  90.     }
  91.  
  92.     /**
  93.      * Decodes the login request procedure.
  94.      * @param ctx The connected {@link ChannelHandlerContext}.
  95.      * @param in The used {@link ByteBuf}.
  96.      * @param out The used output {@link Object}.
  97.      */
  98.     private void decodeLoginRequest(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
  99.         if (!in.isReadable()) { //If the buffer is readable.
  100.             ctx.channel().close();
  101.             return;
  102.         }
  103.         int secureBufferSize = in.readUnsignedShort(); //The size of the buffer to read
  104.         if (in.readableBytes() < secureBufferSize) {
  105.             ctx.channel().close();
  106.             return;
  107.         }
  108.         byte[] secureBytes = new byte[secureBufferSize];
  109.         in.readBytes(secureBytes);
  110.         ByteBuf secureBuffer = Unpooled.wrappedBuffer(new BigInteger(secureBytes).modPow(Protocol.LOGIN_RSA_EXPONENT, Protocol.LOGIN_RSA_MODULUS).toByteArray());
  111.         int blockOpcode = secureBuffer.readUnsignedByte();
  112.         if (blockOpcode != 10) {
  113.             ctx.channel().close();
  114.             return;
  115.         }
  116.         int[] xteaKey = new int[4];
  117.         for (int i = 0; i < xteaKey.length; i++) {
  118.             xteaKey[i] = secureBuffer.readInt();
  119.         }
  120.         long loginHash = secureBuffer.readLong();
  121.         if (loginHash != 0L) {
  122.             ctx.channel().close();
  123.             return;
  124.         }
  125.         String password = BufferUtilities.readBufferedString(secureBuffer); //The password to hash.
  126.         String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt()); //The hashed password.
  127.         secureBuffer.readLong();
  128.         secureBuffer.readLong();
  129.         byte[] xteaBlock = new byte[in.readableBytes()];
  130.         in.readBytes(xteaBlock);
  131.         XTEA xtea = new XTEA(xteaKey);
  132.         xtea.decrypt(xteaBlock, 0, xteaBlock.length);
  133.         ByteBuf xteaBuffer = Unpooled.wrappedBuffer(xteaBlock);
  134.         boolean decodeAsString = xteaBuffer.readByte() == 1;
  135.         String username = Utilities.formatPlayerNameForProtocol(decodeAsString ? BufferUtilities.readBufferedString(xteaBuffer) : Base37Utils.decodeBase37(xteaBuffer.readLong())); //The player username
  136.         switch (loginType) {
  137.         case LOBBY: /
  138.             xteaBuffer.readUnsignedByte();
  139.             xteaBuffer.readUnsignedByte();
  140.             break;
  141.         case WORLD:
  142.             int displayId = xteaBuffer.readUnsignedByte();
  143.             display = (displayId == 1 ? Display.FIXED_DISPLAY : Display.RESIZEABLE_DISPLAY);
  144.             xteaBuffer.readUnsignedShort();
  145.             xteaBuffer.readUnsignedShort();
  146.             xteaBuffer.readUnsignedByte();
  147.             break;
  148.         }
  149.         int[] randomData = new int[24];
  150.         for (int index = 0; index < randomData.length; index++) {
  151.             randomData[index] = xteaBuffer.readUnsignedByte();
  152.         }
  153.         String loginToken = BufferUtilities.readBufferedString(xteaBuffer);
  154.         if (!loginToken.equals(Protocol.LOGIN_TOKEN)) {
  155.             ctx.channel().close();
  156.             return;
  157.         }
  158.         int[] serverKeys = new int[xteaKey.length]; //The 23 CRC keys.
  159.         for (int i = 0; i < xteaKey.length; i++) {
  160.             serverKeys[i] = xteaKey[i] + 50;
  161.         }
  162.         int[] clientKeys = xteaKey;
  163.         IsaacRandom encodingRandom = new IsaacRandom(serverKeys);
  164.         IsaacRandom decodingRandom = new IsaacRandom(clientKeys);
  165.         out.add(new LoginRequestMessage(username, password, hashedPassword, loginType, display, encodingRandom, decodingRandom)); //Decodes the logging in request,
  166.     }
  167.  
  168.     /**
  169.      * An enumeration created that is defining the types of login.
  170.      */
  171.     public enum LoginType {
  172.         LOBBY, WORLD;
  173.     }
  174.  
  175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement