123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /*
- * Copyright (C) 2004-2015 L2J Server
- *
- * This file is part of L2J Server.
- *
- * L2J Server 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 3 of the License, or
- * (at your option) any later version.
- *
- * L2J Server 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, see <http://www.gnu.org/licenses/>.
- */
- package com.l2jserver.gameserver.util;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import com.l2jserver.gameserver.GameTimeController;
- import com.l2jserver.gameserver.instancemanager.PunishmentManager;
- import com.l2jserver.gameserver.model.PcCondOverride;
- import com.l2jserver.gameserver.model.punishment.PunishmentAffect;
- import com.l2jserver.gameserver.model.punishment.PunishmentTask;
- import com.l2jserver.gameserver.model.punishment.PunishmentType;
- import com.l2jserver.gameserver.network.L2GameClient;
- import com.l2jserver.util.StringUtil;
- /**
- * Flood protector implementation.
- * @author fordfrog
- */
- public final class FloodProtectorAction
- {
- /**
- * Logger
- */
- private static final Logger _log = Logger.getLogger(FloodProtectorAction.class.getName());
- /**
- * Client for this instance of flood protector.
- */
- private final L2GameClient _client;
- /**
- * Configuration of this instance of flood protector.
- */
- private final FloodProtectorConfig _config;
- /**
- * Next game tick when new request is allowed.
- */
- private volatile int _nextGameTick = GameTimeController.getInstance().getGameTicks();
- /**
- * Request counter.
- */
- private final AtomicInteger _count = new AtomicInteger(0);
- /**
- * Flag determining whether exceeding request has been logged.
- */
- private boolean _logged;
- /**
- * Flag determining whether punishment application is in progress so that we do not apply punisment multiple times (flooding).
- */
- private volatile boolean _punishmentInProgress;
-
- /**
- * Creates new instance of FloodProtectorAction.
- * @param client the game client for which flood protection is being created
- * @param config flood protector configuration
- */
- public FloodProtectorAction(final L2GameClient client, final FloodProtectorConfig config)
- {
- super();
- _client = client;
- _config = config;
- }
-
- /**
- * Checks whether the request is flood protected or not.
- * @param command command issued or short command description
- * @return true if action is allowed, otherwise false
- */
- public boolean tryPerformAction(final String command)
- {
- final int curTick = GameTimeController.getInstance().getGameTicks();
-
- if ((_client.getActiveChar() != null) && _client.getActiveChar().canOverrideCond(PcCondOverride.FLOOD_CONDITIONS))
- {
- return true;
- }
-
- if ((curTick < _nextGameTick) || _punishmentInProgress)
- {
- if (_config.LOG_FLOODING && !_logged && _log.isLoggable(Level.WARNING))
- {
- log(" called command ", command, " ~", String.valueOf((_config.FLOOD_PROTECTION_INTERVAL - (_nextGameTick - curTick)) * GameTimeController.MILLIS_IN_TICK), " ms after previous command");
- _logged = true;
- }
-
- _count.incrementAndGet();
-
- if (!_punishmentInProgress && (_config.PUNISHMENT_LIMIT > 0) && (_count.get() >= _config.PUNISHMENT_LIMIT) && (_config.PUNISHMENT_TYPE != null))
- {
- _punishmentInProgress = true;
-
- if ("kick".equals(_config.PUNISHMENT_TYPE))
- {
- kickPlayer();
- }
- else if ("ban".equals(_config.PUNISHMENT_TYPE))
- {
- banAccount();
- }
- else if ("jail".equals(_config.PUNISHMENT_TYPE))
- {
- jailChar();
- }
-
- _punishmentInProgress = false;
- }
- return false;
- }
-
- if (_count.get() > 0)
- {
- if (_config.LOG_FLOODING && _log.isLoggable(Level.WARNING))
- {
- log(" issued ", String.valueOf(_count), " extra requests within ~", String.valueOf(_config.FLOOD_PROTECTION_INTERVAL * GameTimeController.MILLIS_IN_TICK), " ms");
- }
- }
-
- _nextGameTick = curTick + _config.FLOOD_PROTECTION_INTERVAL;
- _logged = false;
- _count.set(0);
- return true;
- }
-
- /**
- * Kick player from game (close network connection).
- */
- private void kickPlayer()
- {
- if (_client.getActiveChar() != null)
- {
- _client.getActiveChar().logout(false);
- }
- else
- {
- _client.closeNow();
- }
-
- if (_log.isLoggable(Level.WARNING))
- {
- log("kicked for flooding");
- }
- }
-
- /**
- * Bans char account and logs out the char.
- */
- private void banAccount()
- {
- PunishmentManager.getInstance().startPunishment(new PunishmentTask(_client.getAccountName(), PunishmentAffect.ACCOUNT, PunishmentType.BAN, System.currentTimeMillis() + _config.PUNISHMENT_TIME, "", getClass().getSimpleName()));
- if (_log.isLoggable(Level.WARNING))
- {
- log(" banned for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + (_config.PUNISHMENT_TIME / 60000) + " mins");
- }
- }
-
- /**
- * Jails char.
- */
- private void jailChar()
- {
- if (_client.getActiveChar() != null)
- {
- int charId = _client.getActiveChar().getObjectId();
- if (charId > 0)
- {
- PunishmentManager.getInstance().startPunishment(new PunishmentTask(charId, PunishmentAffect.CHARACTER, PunishmentType.JAIL, System.currentTimeMillis() + _config.PUNISHMENT_TIME, "", getClass().getSimpleName()));
- }
-
- if (_log.isLoggable(Level.WARNING))
- {
- log(" jailed for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + (_config.PUNISHMENT_TIME / 60000) + " mins");
- }
- }
- }
-
- private void log(String... lines)
- {
- final StringBuilder output = StringUtil.startAppend(100, _config.FLOOD_PROTECTOR_TYPE, ": ");
- String address = null;
- try
- {
- if (!_client.isDetached())
- {
- address = _client.getConnection().getInetAddress().getHostAddress();
- }
- }
- catch (Exception e)
- {
- }
-
- switch (_client.getState())
- {
- case IN_GAME:
- if (_client.getActiveChar() != null)
- {
- StringUtil.append(output, _client.getActiveChar().getName());
- StringUtil.append(output, "(", String.valueOf(_client.getActiveChar().getObjectId()), ") ");
- }
- break;
- case AUTHED:
- if (_client.getAccountName() != null)
- {
- StringUtil.append(output, _client.getAccountName(), " ");
- }
- break;
- case CONNECTED:
- if (address != null)
- {
- StringUtil.append(output, address);
- }
- break;
- default:
- throw new IllegalStateException("Missing state on switch");
- }
-
- StringUtil.append(output, lines);
- _log.warning(output.toString());
- }
- }
|