Package com.l2jfrozen.util

Source Code of com.l2jfrozen.util.PacketsFloodProtector

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* http://www.gnu.org/copyleft/gpl.html
*/
package com.l2jfrozen.util;

import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.l2jfrozen.gameserver.controllers.GameTimeController;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.network.L2GameClient;
import com.l2jfrozen.loginserver.L2LoginClient;
import com.l2jfrozen.loginserver.LoginController;
import com.l2jfrozen.loginserver.network.serverpackets.LoginFail.LoginFailReason;
import com.l2jfrozen.netcore.Config;
import com.l2jfrozen.netcore.MMOClient;

/**
* @author Enzo
*/
public class PacketsFloodProtector
{
  private final static int MAX_CONCURRENT_ACTIONS_PER_PLAYER = 10;
 
  private static Hashtable<String, AtomicInteger> clients_concurrent_actions = new Hashtable<String, AtomicInteger>();
 
  private static final Logger _log = Logger.getLogger(PacketsFloodProtector.class.getName());
 
  private static Hashtable<String, Hashtable<Integer, AtomicInteger>> clients_actions = new Hashtable<String, Hashtable<Integer, AtomicInteger>>();
 
  private static Hashtable<String, Hashtable<Integer, Integer>> clients_nextGameTick = new Hashtable<String, Hashtable<Integer, Integer>>();
 
  private static Hashtable<String, Boolean> punishes_in_progress = new Hashtable<String, Boolean>();
 
  /**
   * Checks whether the request is flood protected or not.
   * @param opcode
   * @param opcode2
   * @param client
   * @return true if action is allowed, otherwise false
   */
  public static boolean tryPerformAction(final int opcode, final int opcode2, MMOClient<?> client)
  {
    if (Config.getInstance().DISABLE_FULL_PACKETS_FLOOD_PROTECTOR)
      return true;
   
    // filter on opcodes
    if (!isOpCodeToBeTested(opcode, opcode2, client instanceof L2LoginClient))
      return true;
   
    String account = "";
   
    if (client instanceof L2LoginClient)
    {     
      L2LoginClient login_cl = (L2LoginClient) client;
      account = login_cl.getAccount();     
    }
    else if (client instanceof L2GameClient)
    {     
      L2GameClient game_cl = (L2GameClient) client;
      account = game_cl.accountName;     
    }
   
    if (account == null)
      return true;
   
    // get actual concurrent actions number for account
    AtomicInteger actions_per_account = clients_concurrent_actions.get(account);
    if (actions_per_account == null)
    {
      actions_per_account = new AtomicInteger(0);
    }
    if (actions_per_account.get() < MAX_CONCURRENT_ACTIONS_PER_PLAYER)
    {     
      int actions = actions_per_account.incrementAndGet();
     
      if (Config.getInstance().ENABLE_MMOCORE_DEBUG)
      {
        //_log.info(" -- account " + account + " has performed " + actions + " concurrent actions until now");
      }
     
      clients_concurrent_actions.put(account, actions_per_account);
    }
    else
      return false;
   
    final int curTick = GameTimeController.getGameTicks();
   
    Hashtable<Integer, Integer> account_nextGameTicks = clients_nextGameTick.get(account);
    if (account_nextGameTicks == null)
    {
      account_nextGameTicks = new Hashtable<Integer, Integer>();
    }
    Integer _nextGameTick = account_nextGameTicks.get(opcode);
    if (_nextGameTick == null)
    {
      _nextGameTick = curTick;
      account_nextGameTicks.put(opcode, _nextGameTick);
    }
    clients_nextGameTick.put(account, account_nextGameTicks);
   
    Boolean _punishmentInProgress = punishes_in_progress.get(account);
    if (_punishmentInProgress == null)
    {
      _punishmentInProgress = false;
    }
    else if (_punishmentInProgress)
    {
      AtomicInteger actions = clients_concurrent_actions.get(account);
      actions.decrementAndGet();
      clients_concurrent_actions.put(account, actions);
      return false;
    }
    punishes_in_progress.put(account, _punishmentInProgress);
   
    Hashtable<Integer, AtomicInteger> received_commands_actions = clients_actions.get(account);
    if (received_commands_actions == null)
    {
      received_commands_actions = new Hashtable<Integer, AtomicInteger>();
    }
    AtomicInteger command_count = null;
    if ((command_count = received_commands_actions.get(opcode)) == null)
    {
      command_count = new AtomicInteger(0);
      received_commands_actions.put(opcode, command_count);
    }
    clients_actions.put(account, received_commands_actions);
   
    if (curTick <= _nextGameTick && !_punishmentInProgress) // time to check operations
    {
      command_count.incrementAndGet();
      clients_actions.get(account).put(opcode, command_count);
     
      if (Config.getInstance().ENABLE_MMOCORE_DEBUG)
      {
        //_log.info("-- called OpCode " + Integer.toHexString(opcode) + " ~" + String.valueOf((Config.getInstance().FLOOD_PACKET_PROTECTION_INTERVAL - (_nextGameTick - curTick)) * GameTimeController.MILLIS_IN_TICK) + " ms after first command...");
        //_log.info("   total received packets with OpCode " + Integer.toHexString(opcode) + " into the Interval: " + command_count.get());
      }
     
      if (Config.getInstance().PACKET_FLOODING_PUNISHMENT_LIMIT > 0 && command_count.get() >= Config.getInstance().PACKET_FLOODING_PUNISHMENT_LIMIT && Config.getInstance().PACKET_FLOODING_PUNISHMENT_TYPE != null)
      {
        punishes_in_progress.put(account, true);
       
        if (!isOpCodeToBeTested(opcode, opcode2, client instanceof L2LoginClient))
        {         
          if (Config.getInstance().LOG_PACKET_FLOODING && _log.isLoggable(Level.WARNING))
            //_log.warning("ATTENTION: Account " + account + " is flooding the server...");
         
          if ("kick".equals(Config.getInstance().PACKET_FLOODING_PUNISHMENT_TYPE))
          {
            if (Config.getInstance().LOG_PACKET_FLOODING && _log.isLoggable(Level.WARNING))
              //_log.warning(" ------- kicking account " + account);
            kickPlayer(client, opcode);
          }
          else if ("ban".equals(Config.getInstance().PACKET_FLOODING_PUNISHMENT_TYPE))
          {
            if (Config.getInstance().LOG_PACKET_FLOODING && _log.isLoggable(Level.WARNING))
              //_log.warning(" ------- banning account " + account);
            banAccount(client, opcode);
          }         
        }       
        // clear already punished account
        punishes_in_progress.remove(account);
        clients_nextGameTick.remove(account);
        clients_actions.remove(account);
        clients_concurrent_actions.remove(account);
       
        return false;       
      }
     
      if (curTick == _nextGameTick)
      { // if is the first time, just calculate the next game tick
        _nextGameTick = curTick + Config.getInstance().FLOOD_PACKET_PROTECTION_INTERVAL;
        clients_nextGameTick.get(account).put(opcode, _nextGameTick);
      }
     
      AtomicInteger actions = clients_concurrent_actions.get(account);
      actions.decrementAndGet();
      clients_concurrent_actions.put(account, actions);
     
      return true;     
    }
    punishes_in_progress.put(account, false);
    clients_nextGameTick.get(account).remove(opcode);
    clients_actions.get(account).remove(opcode);
   
    AtomicInteger actions = clients_concurrent_actions.get(account);
    actions.decrementAndGet();
    clients_concurrent_actions.put(account, actions);
   
    return true;   
  }
 
  private static boolean isOpCodeToBeTested(int opcode, int opcode2, boolean loginclient)
  { 
    if (loginclient)
    {     
      return !Config.getInstance().LS_LIST_PROTECTED_OPCODES.contains(opcode);     
    }
   
    if (opcode == 0xd0)
    {     
      if (Config.getInstance().GS_LIST_PROTECTED_OPCODES.contains(opcode))
      {       
        return !Config.getInstance().GS_LIST_PROTECTED_OPCODES2.contains(opcode2);       
      }
      return true;
     
    }
    return !Config.getInstance().GS_LIST_PROTECTED_OPCODES.contains(opcode);
  }
 
  /**
   * Kick player from game (close network connection).
   * @param _client
   * @param opcode
   */
  private static void kickPlayer(MMOClient<?> _client, int opcode)
  {
    if (_client instanceof L2LoginClient)
    {   
      L2LoginClient login_cl = (L2LoginClient) _client;
      login_cl.close(LoginFailReason.REASON_SYSTEM_ERROR);
     
      //_log.warning("Player with account " + login_cl.getAccount() + " kicked for flooding with packet " + Integer.toHexString(opcode));     
    }
    else if (_client instanceof L2GameClient)
    {   
      L2GameClient game_cl = (L2GameClient) _client;
      game_cl.closeNow();
     
      //_log.warning("Player with account " + game_cl.accountName + " kicked for flooding with packet " + Integer.toHexString(opcode));     
    }   
  }
 
  /**
   * Bans char account and logs out the char.
   * @param _client
   * @param opcode
   */
  private static void banAccount(MMOClient<?> _client, int opcode)
  {   
    if (_client instanceof L2LoginClient)
    {     
      L2LoginClient login_cl = (L2LoginClient) _client;
      LoginController.getInstance().setAccountAccessLevel(login_cl.getAccount(), -100);
      login_cl.close(LoginFailReason.REASON_SYSTEM_ERROR);
     
      //_log.warning("Player with account " + login_cl.getAccount() + " banned for flooding forever with packet " + Integer.toHexString(opcode));     
    }
    else if (_client instanceof L2GameClient)
    {     
      L2GameClient game_cl = (L2GameClient) _client;
     
      if (game_cl.getActiveChar() != null)
      {
        game_cl.getActiveChar().setPunishLevel(L2PcInstance.PunishLevel.ACC, 0);     
        //_log.warning("Player " + game_cl.getActiveChar() + " of account " + game_cl.accountName + " banned forever for flooding with packet " + Integer.toHexString(opcode));       
        game_cl.getActiveChar().logout();
      }
     
      game_cl.closeNow();
      //_log.warning("Player with account " + game_cl.accountName + " kicked for flooding with packet " + Integer.toHexString(opcode));     
    }   
  } 
}
TOP

Related Classes of com.l2jfrozen.util.PacketsFloodProtector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.