Advertisement
Guest User

Untitled

a guest
Jul 26th, 2017
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.57 KB | None | 0 0
  1. package server.login;
  2.  
  3. import java.io.IOException;
  4. import java.net.InetAddress;
  5. import java.net.InetSocketAddress;
  6. import java.nio.ByteBuffer;
  7. import java.nio.channels.ServerSocketChannel;
  8. import java.nio.channels.SocketChannel;
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. import java.util.concurrent.TimeUnit;
  12. import java.util.logging.Level;
  13. import java.util.logging.Logger;
  14. import server.net.Cryption;
  15. import server.net.Stream;
  16. import server.world.World;
  17.  
  18. /**
  19.  * Handles waiting logins
  20.  * @author Colby
  21.  */
  22. public class LoginHandler {
  23.  
  24.     private static final Logger log = Logger.getLogger(LoginHandler.class.toString());
  25.  
  26.     public LoginHandler(World world) {
  27.         this.world = world;
  28.         sessions = new ArrayList<LoginSession>(128);
  29.     }
  30.     private final List<LoginSession> sessions;
  31.     public final World world;
  32.  
  33.     public void register(SocketChannel schan) {
  34.         try {
  35.             sessions.add(new LoginSession(schan));
  36.  
  37.         } catch (IOException e) {
  38.             log.throwing(null, null, e);
  39.         }
  40.     }
  41.  
  42.     public void startLogins() {
  43.         log.info("Starting login handler...");
  44.         world.logicService.schedule(createHandlerTask(), 100L, TimeUnit.MILLISECONDS);
  45.     }
  46.  
  47.     public void startServerSock(InetAddress bind, int port) {
  48.         log.log(Level.INFO, "Starting game socket on {0}:{1}", new Object[]{bind, port});
  49.         world.workService.execute(createSocketTask(bind, port));
  50.     }
  51.  
  52.     private Runnable createSocketTask(final InetAddress bind, final int port) {
  53.         return new Runnable() {
  54.  
  55.             public void run() {
  56.  
  57.                 try {
  58.                     ServerSocketChannel listener = null;
  59.                     try {
  60.                         listener = ServerSocketChannel.open();
  61.                         listener.socket().bind(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), port));
  62.  
  63.                         do {
  64.                             try {
  65.                                 SocketChannel schan = listener.accept();
  66.                                 LoginHandler.this.register(schan);
  67.  
  68.                                 log.log(Level.INFO, "New connection: {0}", schan.socket().getInetAddress().getHostAddress());
  69.  
  70.                             } catch (IOException e) {
  71.                                 log.throwing(null, null, e);
  72.                             }
  73.  
  74.                         } while (true);
  75.  
  76.                     } finally {
  77.                         if (listener != null) {
  78.                             listener.close();
  79.                         }
  80.                     }
  81.  
  82.                 } catch (IOException e) {
  83.                     log.throwing(null, null, e);
  84.                 }
  85.             }
  86.         };
  87.     }
  88.  
  89.     private Runnable createHandlerTask() {
  90.         return new Runnable() {
  91.  
  92.             public void run() {
  93.  
  94.                 for (LoginSession session : sessions) {
  95.                     try {
  96.                         if (!session.process()) {
  97.                             sessions.remove(session);
  98.                             if (!session.valid) {
  99.                                 session.schan.close();
  100.  
  101.                             } else {
  102.                                 log.log(Level.INFO, "New player: {0}", session.toString());
  103.                             }
  104.                         }
  105.  
  106.                     } catch (IOException e) {
  107.                         e.printStackTrace();
  108.                     }
  109.                 }
  110.             }
  111.         };
  112.     }
  113.  
  114.     public static class LoginSession {
  115.  
  116.         public LoginSession(SocketChannel schan) throws IOException {
  117.             if (schan.isBlocking()) {
  118.                 schan.configureBlocking(false);
  119.             }
  120.             schan.socket().setTcpNoDelay(true);
  121.             schan.socket().setSoTimeout(10000);
  122.             this.schan = schan;
  123.  
  124.             inBuffer = ByteBuffer.allocate(128);
  125.             outBuffer = ByteBuffer.allocate(128);
  126.  
  127.             inStream = new Stream(inBuffer.array());
  128.             outStream = new Stream(outBuffer.array());
  129.  
  130.             serverSessionKey = ((long) (Math.random() * 99999999D) << 32) + (long) (Math.random() * 99999999D);
  131.         }
  132.         private Stage stage = Stage.First;
  133.         private Stream inStream, outStream;
  134.         private ByteBuffer inBuffer, outBuffer;
  135.         private SocketChannel schan;
  136.         private long serverSessionKey;
  137.         private int loginPacketSize, loginEncryptPacketSize;
  138.         public boolean valid;
  139.  
  140.         public static enum Stage {
  141.  
  142.             First(2),
  143.             Second(2),
  144.             Third(-1),
  145.             Done(-1);
  146.  
  147.             Stage(int len) {
  148.                 this.len = len;
  149.             }
  150.             public final int len;
  151.         }
  152.  
  153.         @Override
  154.         public String toString() {
  155.             return schan.socket().getInetAddress().getHostAddress();
  156.         }
  157.  
  158.         public boolean process() throws IOException {
  159.             inBuffer.flip();
  160.             schan.read(inBuffer);
  161.             inBuffer.flip();
  162.             if (inBuffer.remaining() < ((stage == Stage.Third) ? loginPacketSize : stage.len)) {
  163.                 return true;
  164.             }
  165.             inStream.currentOffset = inBuffer.position();
  166.             outStream.currentOffset = outBuffer.position();
  167.  
  168.             switch (stage) {
  169.  
  170.                 case First:
  171.                     int lType = inStream.readUnsignedByte();
  172.                     if (lType != 14) {
  173.                         error("Unexpected login type: " + lType);
  174.                         return false;
  175.                     }
  176.  
  177.                     int nameHash = inStream.readUnsignedByte();
  178.  
  179.                     //Prevent timeout
  180.                     for (int i = 0; i < 8; i++) {
  181.                         outStream.writeByte(0);
  182.                     }
  183.                     // 0=crypt, 2=skip
  184.                     outStream.writeByte(0);
  185.                     outStream.writeQWord(serverSessionKey);
  186.  
  187.                     stage = Stage.Second;
  188.                     break;
  189.  
  190.                 case Second:
  191.                     //16=new, 18=reconnect
  192.                     int loginType = inStream.readUnsignedByte();
  193.                     if (loginType != 16 && loginType != 18) {
  194.                         error("Unexpected login type " + loginType);
  195.                         return false;
  196.                     }
  197.                     loginPacketSize = inStream.readUnsignedByte();
  198.                     // the size of the RSA encrypted part (containing password)
  199.                     loginEncryptPacketSize = loginPacketSize - (36 + 1 + 1 + 2);
  200.                     if (loginEncryptPacketSize <= 0) {
  201.                         error("Zero RSA packet size!");
  202.                         return false;
  203.                     }
  204.                     stage = Stage.Third;
  205.                     break;
  206.  
  207.                 case Third:
  208.                     int i1 = inStream.readUnsignedByte();
  209.                     int i0 = inStream.readUnsignedWord();
  210.                     if (i1 != 255 || i0 != 317) {
  211.                         error("Wrong login packet magic ID (expected 255, 317): " + i1 + ":" + i0);
  212.                         return false;
  213.                     }
  214.                     int lowMemoryVersion = inStream.readUnsignedByte();
  215.                     for (int i = 0; i < 9; i++) {
  216.                         inStream.readDWord();
  217.                     }
  218.                     // don't count length byte
  219.                     loginEncryptPacketSize--;
  220.                     int tmp = inStream.readUnsignedByte();
  221.                     if (loginEncryptPacketSize != tmp) {
  222.                         error("Encrypted packet data length (" + loginEncryptPacketSize + ") different from length byte thereof (" + tmp + ")");
  223.                         return false;
  224.                     }
  225.                     tmp = inStream.readUnsignedByte();
  226.                     if (tmp != 10) {
  227.                         error("Encrypted packet Id was " + tmp + " but expected 10");
  228.                         return false;
  229.                     }
  230.                     long clientSessionKey = inStream.readQWord();
  231.                     serverSessionKey = inStream.readQWord();
  232.  
  233.                     int uid = inStream.readDWord();
  234.  
  235.                     String username = inStream.readString().replaceAll(" ", "_").toLowerCase();
  236.                     String password = inStream.readString().replaceAll(" ", "_").toLowerCase();
  237.  
  238.                     int sessionKey[] = new int[4];
  239.                     sessionKey[0] = (int) (clientSessionKey >> 32);
  240.                     sessionKey[1] = (int) clientSessionKey;
  241.                     sessionKey[2] = (int) (serverSessionKey >> 32);
  242.                     sessionKey[3] = (int) serverSessionKey;
  243.  
  244.                     inStream.packetEncryption = new Cryption(sessionKey);
  245.                     for (int i = 0; i < 4; i++) {
  246.                         sessionKey[i] += 50;
  247.                     }
  248.                     outStream.packetEncryption = new Cryption(sessionKey);
  249.  
  250.                     outStream.writeByte(2);
  251.                     outStream.writeByte(2);
  252.                     outStream.writeByte(0);
  253.                     valid = true;
  254.                     break;
  255.  
  256.             }
  257.             outBuffer.position(outStream.currentOffset);
  258.             outBuffer.flip();
  259.             schan.write(outBuffer);
  260.             if (outBuffer.remaining() == 0) {
  261.                 return false;
  262.             }
  263.             outBuffer.flip();
  264.             return true;
  265.         }
  266.  
  267.         private void error(String msg) {
  268.             log.log(Level.WARNING, "[{0}]:{1}", new Object[]{schan.socket().getInetAddress().getHostAddress(), msg});
  269.         }
  270.     }
  271. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement