Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package org.hyperion.rs2.net;
- import java.security.SecureRandom;
- import java.util.logging.Logger;
- import java.util.LinkedList;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import org.apache.mina.core.buffer.IoBuffer;
- import org.apache.mina.core.session.IoSession;
- import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
- import org.apache.mina.filter.codec.ProtocolCodecFilter;
- import org.apache.mina.filter.codec.ProtocolDecoderOutput;
- import org.hyperion.Server;
- import org.hyperion.cache.UpdateServer;
- import org.hyperion.rs2.model.PlayerDetails;
- import org.hyperion.rs2.model.World;
- import org.hyperion.rs2.util.IoBufferUtils;
- import org.hyperion.rs2.util.NameUtils;
- import org.hyperion.rs2.util.TextUtils;
- public class RS2LoginDecoder extends CumulativeProtocolDecoder {
- /**
- * Logger instance.
- */
- private static final Logger logger = Logger.getLogger(RS2LoginDecoder.class.getName());
- /**
- * Opcode stage.
- */
- public static final int STATE_OPCODE = 0;
- /**
- * Precrypted stage.
- */
- public static final int STATE_PRECRYPTED = 2;
- /**
- * Crypted stage.
- */
- public static final int STATE_CRYPTED = 3;
- /**
- * Client Rev Check stage.
- */
- public static final int STATE_CRC = 1;
- /**
- * Update stage.
- */
- public static final int STATE_UPDATE = -1;
- /**
- * Game opcode.
- */
- public static final int OPCODE_GAME = 14;
- /**
- * Update opcode.
- */
- public static final int OPCODE_UPDATE = 15;
- /**
- * Secure random number generator.
- */
- private static final SecureRandom RANDOM = new SecureRandom();
- private LinkedList<Request> requests = new LinkedList<Request>();
- private static ExecutorService updateService = Executors.newFixedThreadPool(1);
- /**
- * Initial login response.
- */
- private static final byte[] INITIAL_RESPONSE = new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- @Override
- protected boolean doDecode(final IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
- synchronized(session) {
- int state = (Integer) session.getAttribute("state", STATE_OPCODE);
- switch(state) {
- case STATE_UPDATE:
- if(in.remaining() >= 4) {
- int type = in.get() & 0xff;
- final int cache = in.get() & 0xff;
- final int id = in.getShort() & 0xffff;
- switch (type) {
- case 0: // non-urgent
- requests.add(new Request(cache, id));
- break;
- case 1: // urgent
- updateService.execute(new Runnable() {
- @Override
- public void run() {
- session.write(UpdateServer.getPacketRequest(cache, id));
- }
- });
- break;
- case 2: // clear requests
- case 3:
- requests.clear();
- break;
- case 4: // client error
- break;
- }
- while (requests.size() > 0) {
- Request request = (Request) requests.removeFirst();
- session.write(UpdateServer.getPacketRequest(request.getCache(), request.getId()));
- }
- return true;
- } else {
- in.rewind();
- return false;
- }
- case STATE_CRC:
- if(in.remaining() >= 3) {
- in.get();
- int version = in.getShort();
- if (version == Server.VERSION) {
- session.write(new PacketBuilder().put((byte) 0).toPacket());
- session.setAttribute("state", STATE_UPDATE);
- } else {
- session.write(new PacketBuilder().put((byte) 6).toPacket());
- session.removeAttribute("state");
- }
- return true;
- }
- break;
- case STATE_OPCODE:
- if(in.remaining() >= 2) {
- int opcode = in.get() & 0xFF;
- int hash = in.get() & 0xFF;
- switch(opcode) {
- case OPCODE_GAME:
- long serverKey = RANDOM.nextLong();
- session.write(new PacketBuilder().put((byte) 0).putLong(serverKey).toPacket());
- session.setAttribute("serverKey", serverKey);
- session.setAttribute("state", STATE_PRECRYPTED);
- return true;
- case OPCODE_UPDATE:
- session.setAttribute("state", STATE_CRC);
- return true;
- default:
- logger.info("Invalid opcode : " + opcode);
- session.close(false);
- break;
- }
- } else {
- in.rewind();
- return false;
- }
- break;
- case STATE_PRECRYPTED:
- if(in.remaining() >= 2) {
- int loginOpcode = in.get() & 0xFF;
- if(loginOpcode != 16 && loginOpcode != 18) {
- logger.info("Invalid login opcode : " + loginOpcode);
- session.close(false);
- in.rewind();
- return false;
- }
- int loginSize = in.get() & 0xFF;
- int loginEncryptSize = loginSize - (36 + 1 + 1 + 2);
- session.setAttribute("state", STATE_CRYPTED);
- session.setAttribute("size", loginSize);
- session.setAttribute("encryptSize", loginEncryptSize);
- return true;
- }
- break;
- case STATE_CRYPTED:
- int size = (Integer) session.getAttribute("size");
- int encryptSize = (Integer) session.getAttribute("encryptSize");
- if(in.remaining() >= size) {
- int version = in.getInt();
- if(version != Server.VERSION) {
- logger.info("Incorrect version : " + version);
- session.close(false);
- in.rewind();
- return false;
- }
- in.get();
- in.get();
- for(int i = 0; i < 16; i++) {
- in.getInt();
- }
- int blockOpcode = in.get() & 0xFF;
- if(blockOpcode != 10) {
- logger.info("Invalid login block opcode : " + blockOpcode);
- session.close(false);
- in.rewind();
- return false;
- }
- int[] sessionKey = new int[4];
- for(int i = 0; i < 4; i++) {
- sessionKey[i] = in.getInt();
- }
- int uid = in.getInt();
- logger.info("Size: "+in.remaining());
- String name = NameUtils.formatName(NameUtils.longToName(in.getLong()));
- String pass = IoBufferUtils.getRS2String(in).trim();
- logger.info("Login request : username=" + name + " password=" + pass);
- session.removeAttribute("state");
- session.removeAttribute("serverKey");
- session.removeAttribute("size");
- session.removeAttribute("encryptSize");
- ISAACCipher inCipher = new ISAACCipher(sessionKey);
- for(int i = 0; i < 4; i++) {
- sessionKey[i] += 50;
- }
- ISAACCipher outCipher = new ISAACCipher(sessionKey);
- session.getFilterChain().remove("protocol");
- session.getFilterChain().addFirst("protocol", new ProtocolCodecFilter(RS2CodecFactory.GAME));
- PlayerDetails pd = new PlayerDetails(session, name, pass, 0, inCipher, outCipher);
- World.getWorld().load(pd);
- }
- break;
- }
- in.rewind();
- return false;
- }
- }
- private static class Request {
- private int cache;
- private int id;
- public Request(int cache, int id) {
- this.cache = cache;
- this.id = id;
- }
- public int getCache() {
- return cache;
- }
- public int getId() {
- return id;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement