Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class GameServerThread extends Thread
- {
- private static final Logger _log = LogManager.getLogger(GameServerThread.class.getName());
- private Socket _connection;
- private InputStream _in;
- private OutputStream _out;
- private RSAPublicKey _publicKey;
- private RSAPrivateKey _privateKey;
- private NewCrypt _blowfish;
- private byte[] _blowfishKey;
- private String _connectionIp;
- private GameServerInfo _gsi;
- /** Authed Clients on a GameServer */
- private Set<String> _accountsOnGameServer = new FastSet<String>();
- private String _connectionIPAddress;
- @Override
- public void run()
- {
- boolean checkTime = true;
- long time = System.currentTimeMillis();
- _connectionIPAddress = _connection.getInetAddress().getHostAddress();
- if(GameServerThread.isBannedGameserverIP(_connectionIPAddress))
- {
- _log.info("IP Address " + _connectionIPAddress + " is on banned IP(s) list");
- forceClose(LoginServerFail.REASON_IP_BANNED);
- // ensure no further processing for this connection
- return;
- }
- InitLS startPacket = new InitLS(_publicKey.getModulus().toByteArray());
- try
- {
- sendPacket(startPacket);
- int lengthHi = 0;
- int lengthLo = 0;
- int length = 0;
- boolean checksumOk = false;
- while(true)
- {
- if(time - System.currentTimeMillis() > 10000 && checkTime)
- {
- _connection.close();
- break;
- }
- try
- {
- lengthLo = _in.read();
- lengthHi = _in.read();
- length = lengthHi * 256 + lengthLo;
- }
- catch(IOException e)
- {
- lengthHi = -1;
- /*
- String serverName = getServerId() != -1 ? "[" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) : "(" + _connectionIPAddress + ")";
- String msg = "GameServer " + serverName + ": Connection lost: " + e.getMessage();
- _log.info(msg);
- serverName = null;
- msg = null;
- */
- }
- if(lengthHi < 0 || _connection.isClosed())
- {
- if(Config.DEBUG)
- _log.debug("Login terminated the connection");
- break;
- }
- byte[] data = new byte[length - 2];
- int receivedBytes = 0;
- int newBytes = 0;
- while(newBytes != -1 && receivedBytes < length - 2)
- {
- newBytes = _in.read(data, 0, length - 2);
- receivedBytes = receivedBytes + newBytes;
- }
- if(receivedBytes != length - 2)
- {
- _log.warn("Incomplete Packet is sent to the server, closing connection ...");
- break;
- }
- // decrypt if we have a key
- data = _blowfish.decrypt(data);
- checksumOk = NewCrypt.verifyChecksum(data);
- if(!checksumOk)
- {
- _log.warn("Incorrect packet checksum, closing connection ...");
- return;
- }
- if(Config.DEBUG){
- _log.warn("[C]\n" + Util.printData(data));
- }
- int packetType = data[0] & 0xff;
- switch(packetType)
- {
- case 00:
- checkTime = false;
- onReceiveBlowfishKey(data);
- break;
- case 01:
- onGameServerAuth(data);
- break;
- case 02:
- onReceivePlayerInGame(data);
- break;
- case 03:
- onReceivePlayerLogOut(data);
- break;
- case 04:
- onReceiveChangeAccessLevel(data);
- break;
- case 05:
- onReceivePlayerAuthRequest(data);
- break;
- case 06:
- onReceiveServerStatus(data);
- break;
- case 0x1F:
- new ChangePassword(data);
- break;
- default:
- _log.warn("Unknown Opcode (" + Integer.toHexString(packetType).toUpperCase() + ") from GameServer, closing connection ...");
- forceClose(LoginServerFail.NOT_AUTHED);
- }
- }
- }
- catch(IOException e)
- {
- if(Config.ENABLE_ALL_EXCEPTIONS)
- e.printStackTrace();
- String serverName = getServerId() != -1 ? "[" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) : "(" + _connectionIPAddress + ")";
- String msg = "GameServer " + serverName + ": Connection lost: " + e.getMessage();
- _log.info(msg);
- serverName = null;
- msg = null;
- }
- finally
- {
- if(isAuthed())
- {
- _gsi.setDown();
- _log.info("Server [" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) + " is now set as disconnected");
- }
- L2LoginServer.getInstance().getGameServerListener().removeGameServer(this);
- L2LoginServer.getInstance().getGameServerListener().removeFloodProtection(_connectionIp);
- }
- startPacket = null;
- }
- private void onReceiveBlowfishKey(byte[] data)
- {
- /*if (_blowfish == null)
- {*/
- BlowFishKey bfk = new BlowFishKey(data, _privateKey);
- _blowfishKey = bfk.getKey();
- _blowfish = new NewCrypt(_blowfishKey);
- if(Config.DEBUG){
- _log.debug("New BlowFish key received, Blowfih Engine initialized: ");
- }
- /*}
- else
- {
- _log.warn("GameServer attempted to re-initialize the blowfish key.");
- // TODO get a better reason
- this.forceClose(LoginServerFail.NOT_AUTHED);
- }*/
- bfk = null;
- }
- private void onGameServerAuth(byte[] data) throws IOException
- {
- GameServerAuth gsa = new GameServerAuth(data);
- if(Config.DEBUG){
- _log.debug("Auth request received");
- }
- handleRegProcess(gsa);
- if(isAuthed())
- {
- AuthResponse ar = new AuthResponse(getGameServerInfo().getId());
- sendPacket(ar);
- if(Config.DEBUG){
- _log.debug("Authed id: " + getGameServerInfo().getId());
- }
- ar = null;
- }
- gsa = null;
- }
- private void onReceivePlayerInGame(byte[] data)
- {
- if(isAuthed())
- {
- PlayerInGame pig = new PlayerInGame(data);
- List<String> newAccounts = pig.getAccounts();
- for(String account : newAccounts)
- {
- _accountsOnGameServer.add(account);
- if(Config.DEBUG){
- _log.debug("Account " + account + " logged in GameServer: [" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()));
- }
- }
- pig = null;
- newAccounts = null;
- }
- else{
- forceClose(LoginServerFail.NOT_AUTHED);
- }
- }
- private void onReceivePlayerLogOut(byte[] data)
- {
- if(isAuthed())
- {
- PlayerLogout plo = new PlayerLogout(data);
- _accountsOnGameServer.remove(plo.getAccount());
- if(Config.DEBUG){
- _log.debug("Player " + plo.getAccount() + " logged out from GameServer [" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()));
- }
- plo = null;
- }
- else{
- forceClose(LoginServerFail.NOT_AUTHED);
- }
- }
- private void onReceiveChangeAccessLevel(byte[] data)
- {
- if(isAuthed())
- {
- ChangeAccessLevel cal = new ChangeAccessLevel(data);
- LoginController.getInstance().setAccountAccessLevel(cal.getAccount(), cal.getLevel());
- cal = null;
- }
- else{
- forceClose(LoginServerFail.NOT_AUTHED);
- }
- }
- private void onReceivePlayerAuthRequest(byte[] data) throws IOException
- {
- if(isAuthed())
- {
- PlayerAuthRequest par = new PlayerAuthRequest(data);
- PlayerAuthResponse authResponse;
- if(Config.DEBUG){
- _log.debug("Auth request received for Player `" + par.getAccount() + "`");
- }
- SessionKey key = LoginController.getInstance().getKeyForAccount(par.getAccount());
- if(key != null && key.equals(par.getKey()))
- {
- if(Config.DEBUG){
- _log.debug("Auth request: OK");
- }
- LoginController.getInstance().removeAuthedLoginClient(par.getAccount());
- authResponse = new PlayerAuthResponse(par.getAccount(), true);
- }
- else
- {
- if(Config.DEBUG)
- {
- _log.debug("Auth request: NO");
- _log.debug("Session key from self: " + key);
- _log.debug("Session key sent: " + par.getKey());
- }
- authResponse = new PlayerAuthResponse(par.getAccount(), false);
- }
- sendPacket(authResponse);
- par = null;
- authResponse = null;
- key = null;
- }
- else
- {
- forceClose(LoginServerFail.NOT_AUTHED);
- }
- }
- private void onReceiveServerStatus(byte[] data)
- {
- if(isAuthed())
- {
- if(Config.DEBUG){
- _log.debug("ServerStatus received");
- }
- /*ServerStatus ss = */new ServerStatus(data, getServerId()); //server status
- }
- else{
- forceClose(LoginServerFail.NOT_AUTHED);
- }
- }
- private void handleRegProcess(GameServerAuth gameServerAuth)
- {
- GameServerTable gameServerTable = GameServerTable.getInstance();
- int id = gameServerAuth.getDesiredID();
- byte[] hexId = gameServerAuth.getHexID();
- GameServerInfo gsi = gameServerTable.getRegisteredGameServerById(id);
- // is there a gameserver registered with this id?
- if(gsi != null)
- {
- // does the hex id match?
- if(Arrays.equals(gsi.getHexId(), hexId))
- {
- // check to see if this GS is already connected
- synchronized(gsi)
- {
- if(gsi.isAuthed()){
- forceClose(LoginServerFail.REASON_ALREADY_LOGGED8IN);
- }else{
- attachGameServerInfo(gsi, gameServerAuth);
- }
- }
- }
- else
- {
- // there is already a server registered with the desired id and different hex id
- // try to register this one with an alternative id
- if(Config.ACCEPT_NEW_GAMESERVER && gameServerAuth.acceptAlternateID())
- {
- gsi = new GameServerInfo(id, hexId, this);
- if(gameServerTable.registerWithFirstAvaliableId(gsi))
- {
- attachGameServerInfo(gsi, gameServerAuth);
- gameServerTable.registerServerOnDB(gsi);
- }
- else
- {
- forceClose(LoginServerFail.REASON_NO_FREE_ID);
- }
- }
- else
- {
- // server id is already taken, and we cant get a new one for you
- forceClose(LoginServerFail.REASON_WRONG_HEXID);
- }
- }
- }
- else
- {
- // can we register on this id?
- if(Config.ACCEPT_NEW_GAMESERVER)
- {
- gsi = new GameServerInfo(id, hexId, this);
- if(gameServerTable.register(id, gsi))
- {
- attachGameServerInfo(gsi, gameServerAuth);
- gameServerTable.registerServerOnDB(gsi);
- }
- else
- {
- // some one took this ID meanwhile
- forceClose(LoginServerFail.REASON_ID_RESERVED);
- }
- }
- else
- {
- forceClose(LoginServerFail.REASON_WRONG_HEXID);
- }
- }
- gameServerTable = null;
- gsi = null;
- }
- public boolean hasAccountOnGameServer(String account)
- {
- return _accountsOnGameServer.contains(account);
- }
- public int getPlayerCount()
- {
- return _accountsOnGameServer.size();
- }
- /**
- * Attachs a GameServerInfo to this Thread <li>Updates the GameServerInfo values based on GameServerAuth packet</li>
- * <li><b>Sets the GameServerInfo as Authed</b></li>
- *
- * @param gsi The GameServerInfo to be attached.
- * @param gameServerAuth The server info.
- */
- private void attachGameServerInfo(GameServerInfo gsi, GameServerAuth gameServerAuth)
- {
- setGameServerInfo(gsi);
- gsi.setGameServerThread(this);
- gsi.setPort(gameServerAuth.getPort());
- setGameHosts(gameServerAuth.getExternalHost(), gameServerAuth.getInternalHost());
- gsi.setMaxPlayers(gameServerAuth.getMaxPlayers());
- gsi.setAuthed(true);
- }
- private void forceClose(int reason)
- {
- LoginServerFail lsf = new LoginServerFail(reason);
- try{
- sendPacket(lsf);
- }
- catch(IOException e)
- {
- if(Config.ENABLE_ALL_EXCEPTIONS)
- e.printStackTrace();
- _log.warn("Failed kicking banned server. Reason: " + e.getMessage());
- }
- try{
- _connection.close();
- }
- catch(IOException e)
- {
- if(Config.ENABLE_ALL_EXCEPTIONS)
- e.printStackTrace();
- _log.warn("Failed disconnecting banned server, server already disconnected.");
- }
- lsf = null;
- }
- /*
- private void handleRegisterationProcess(GameServerAuth gameServerauth)
- {
- try
- {
- GameServerTable gsTableInstance = GameServerTable.getInstance();
- if (gsTableInstance.isARegisteredServer(gameServerauth.getHexID()))
- {
- if (Config.DEBUG)
- {
- _log.info("Valid HexID");
- }
- _server_id = gsTableInstance.getServerIDforHex(gameServerauth.getHexID());
- if (gsTableInstance.isServerAuthed(_server_id))
- {
- LoginServerFail lsf = new LoginServerFail(LoginServerFail.REASON_ALREADY_LOGGED8IN);
- sendPacket(lsf);
- _connection.close();
- return;
- }
- _gamePort = gameServerauth.getPort();
- setGameHosts(gameServerauth.getExternalHost(), gameServerauth.getInternalHost());
- _max_players = gameServerauth.getMaxPlayers();
- _hexID = gameServerauth.getHexID();
- //gsTableInstance.addServer(this);
- }
- else if (Config.ACCEPT_NEW_GAMESERVER)
- {
- if (Config.DEBUG)
- {
- _log.info("New HexID");
- }
- if(!gameServerauth.acceptAlternateID())
- {
- if(gsTableInstance.isIDfree(gameServerauth.getDesiredID()))
- {
- if (Config.DEBUG)_log.info("Desired ID is Valid");
- _server_id = gameServerauth.getDesiredID();
- _gamePort = gameServerauth.getPort();
- setGameHosts(gameServerauth.getExternalHost(), gameServerauth.getInternalHost());
- _max_players = gameServerauth.getMaxPlayers();
- _hexID = gameServerauth.getHexID();
- gsTableInstance.createServer(this);
- //gsTableInstance.addServer(this);
- }
- else
- {
- LoginServerFail lsf = new LoginServerFail(LoginServerFail.REASON_ID_RESERVED);
- sendPacket(lsf);
- _connection.close();
- return;
- }
- }
- else
- {
- int id;
- if(!gsTableInstance.isIDfree(gameServerauth.getDesiredID()))
- {
- id = gsTableInstance.findFreeID();
- if (Config.DEBUG)_log.info("Affected New ID:"+id);
- if(id < 0)
- {
- LoginServerFail lsf = new LoginServerFail(LoginServerFail.REASON_NO_FREE_ID);
- sendPacket(lsf);
- _connection.close();
- return;
- }
- }
- else
- {
- id = gameServerauth.getDesiredID();
- if (Config.DEBUG)_log.info("Desired ID is Valid");
- }
- _server_id = id;
- _gamePort = gameServerauth.getPort();
- setGameHosts(gameServerauth.getExternalHost(), gameServerauth.getInternalHost());
- _max_players = gameServerauth.getMaxPlayers();
- _hexID = gameServerauth.getHexID();
- gsTableInstance.createServer(this);
- //gsTableInstance.addServer(this);
- }
- }
- else
- {
- _log.info("Wrong HexID");
- LoginServerFail lsf = new LoginServerFail(LoginServerFail.REASON_WRONG_HEXID);
- sendPacket(lsf);
- _connection.close();
- return;
- }
- }
- catch (IOException e)
- {
- _log.info("Error while registering GameServer "+GameServerTable.getInstance().serverNames.get(_server_id)+" (ID:"+_server_id+")");
- }
- }
- */
- public static boolean isBannedGameserverIP(String ipAddress)
- {
- return false;
- }
- public GameServerThread(Socket con)
- {
- _connection = con;
- _connectionIp = con.getInetAddress().getHostAddress();
- try
- {
- _in = _connection.getInputStream();
- _out = new BufferedOutputStream(_connection.getOutputStream());
- }
- catch(IOException e){
- e.printStackTrace();
- }
- KeyPair pair = GameServerTable.getInstance().getKeyPair();
- _privateKey = (RSAPrivateKey) pair.getPrivate();
- _publicKey = (RSAPublicKey) pair.getPublic();
- _blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
- }
- private void sendPacket(ServerBasePacket sl) throws IOException
- {
- byte[] data = sl.getContent();
- NewCrypt.appendChecksum(data);
- if(Config.DEBUG){
- _log.debug("[S] " + sl.getClass().getSimpleName() + ":\n" + Util.printData(data));
- }
- data = _blowfish.crypt(data);
- int len = data.length + 2;
- synchronized(_out)
- {
- _out.write(len & 0xff);
- _out.write(len >> 8 & 0xff);
- _out.write(data);
- _out.flush();
- }
- data = null;
- }
- public void kickPlayer(String account)
- {
- KickPlayer kp = new KickPlayer(account);
- try{
- sendPacket(kp);
- }
- catch(IOException e){
- e.printStackTrace();
- }
- kp = null;
- }
- public void ChangePasswordResponse(byte successful, String characterName, String msgToSend)
- {
- ChangePasswordResponse cpr = new ChangePasswordResponse(successful, characterName, msgToSend);
- try{
- sendPacket(cpr);
- }
- catch(IOException e){
- e.printStackTrace();
- }
- }
- public void setGameHosts(String gameExternalHost, String gameInternalHost)
- {
- String oldInternal = _gsi.getInternalHost();
- String oldExternal = _gsi.getExternalHost();
- _gsi.setExternalHost(gameExternalHost);
- _gsi.setInternalIp(gameInternalHost);
- if(!gameExternalHost.equals("*"))
- {
- try{
- _gsi.setExternalIp(InetAddress.getByName(gameExternalHost).getHostAddress());
- }
- catch(UnknownHostException e)
- {
- if(Config.ENABLE_ALL_EXCEPTIONS)
- e.printStackTrace();
- _log.warn("Could not resolve hostname \"" + gameExternalHost + "\"");
- }
- }
- else{
- _gsi.setExternalIp(_connectionIp);
- }
- if(!gameInternalHost.equals("*"))
- {
- try{
- _gsi.setInternalIp(InetAddress.getByName(gameInternalHost).getHostAddress());
- }
- catch(UnknownHostException e)
- {
- if(Config.ENABLE_ALL_EXCEPTIONS)
- e.printStackTrace();
- _log.warn("Could not resolve hostname \"" + gameInternalHost + "\"");
- }
- }
- else{
- _gsi.setInternalIp(_connectionIp);
- }
- _log.info("Updated GameServer [" + getServerId() + "] " + GameServerTable.getInstance().getServerNameById(getServerId()) + " IP's: ");
- if(oldInternal == null || !oldInternal.equalsIgnoreCase(gameInternalHost))
- {
- _log.info("InternalIP: " + gameInternalHost);
- }
- if(oldExternal == null || !oldExternal.equalsIgnoreCase(gameExternalHost))
- {
- _log.info("ExternalIP: " + gameExternalHost);
- }
- oldInternal = null;
- oldExternal = null;
- }
- public boolean isAuthed()
- {
- if(getGameServerInfo() == null)
- return false;
- return getGameServerInfo().isAuthed();
- }
- public void setGameServerInfo(GameServerInfo gsi)
- {
- _gsi = gsi;
- }
- public GameServerInfo getGameServerInfo()
- {
- return _gsi;
- }
- public String getConnectionIpAddress()
- {
- return _connectionIPAddress;
- }
- private int getServerId()
- {
- if(getGameServerInfo() != null)
- return getGameServerInfo().getId();
- return -1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement