Removal of ClientStats and GameClient minor cleanup.
This commit is contained in:
@@ -1152,14 +1152,6 @@ public class Config
|
||||
|
||||
/** Client Packets Queue settings */
|
||||
public static final int CLIENT_PACKET_QUEUE_SIZE = 14; // default MMO_MAX_READ_PER_PASS + 2
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_BURST_SIZE = 13; // default MMO_MAX_READ_PER_PASS + 1
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_PACKETS_PER_SECOND = 160; // default 160
|
||||
public static final int CLIENT_PACKET_QUEUE_MEASURE_INTERVAL = 5; // default 5
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_AVERAGE_PACKETS_PER_SECOND = 80; // default 80
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_FLOODS_PER_MIN = 2; // default 2
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_OVERFLOWS_PER_MIN = 1; // default 1
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_UNDERFLOWS_PER_MIN = 1; // default 1
|
||||
public static final int CLIENT_PACKET_QUEUE_MAX_UNKNOWN_PER_MIN = 5; // default 5
|
||||
|
||||
/** Packet handler settings */
|
||||
public static final boolean PACKET_HANDLER_DEBUG = false;
|
||||
|
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.network;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
|
||||
public class ClientStats
|
||||
{
|
||||
public int processedPackets = 0;
|
||||
public int droppedPackets = 0;
|
||||
public int unknownPackets = 0;
|
||||
public int totalQueueSize = 0;
|
||||
public int maxQueueSize = 0;
|
||||
public int totalBursts = 0;
|
||||
public int maxBurstSize = 0;
|
||||
public int shortFloods = 0;
|
||||
public int longFloods = 0;
|
||||
public int totalQueueOverflows = 0;
|
||||
public int totalUnderflowExceptions = 0;
|
||||
|
||||
private final int[] _packetsInSecond;
|
||||
private long _packetCountStartTick = 0;
|
||||
private int _head;
|
||||
private int _totalCount = 0;
|
||||
|
||||
private int _floodsInMin = 0;
|
||||
private long _floodStartTick = 0;
|
||||
private int _unknownPacketsInMin = 0;
|
||||
private long _unknownPacketStartTick = 0;
|
||||
private int _overflowsInMin = 0;
|
||||
private long _overflowStartTick = 0;
|
||||
private int _underflowReadsInMin = 0;
|
||||
private long _underflowReadStartTick = 0;
|
||||
|
||||
private volatile boolean _floodDetected = false;
|
||||
private volatile boolean _queueOverflowDetected = false;
|
||||
|
||||
private final int BUFFER_SIZE;
|
||||
|
||||
public ClientStats()
|
||||
{
|
||||
BUFFER_SIZE = Config.CLIENT_PACKET_QUEUE_MEASURE_INTERVAL;
|
||||
_packetsInSecond = new int[BUFFER_SIZE];
|
||||
_head = BUFFER_SIZE - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if incoming packet need to be dropped.
|
||||
*/
|
||||
protected final boolean dropPacket()
|
||||
{
|
||||
final boolean result = _floodDetected || _queueOverflowDetected;
|
||||
if (result)
|
||||
{
|
||||
droppedPackets++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param queueSize
|
||||
* @return true if flood detected first and ActionFailed packet need to be sent. Later during flood returns true (and send ActionFailed) once per second.
|
||||
*/
|
||||
protected final boolean countPacket(int queueSize)
|
||||
{
|
||||
processedPackets++;
|
||||
totalQueueSize += queueSize;
|
||||
if (maxQueueSize < queueSize)
|
||||
{
|
||||
maxQueueSize = queueSize;
|
||||
}
|
||||
if (_queueOverflowDetected && (queueSize < 2))
|
||||
{
|
||||
_queueOverflowDetected = false;
|
||||
}
|
||||
return countPacket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts unknown packets.
|
||||
* @return true if threshold is reached.
|
||||
*/
|
||||
protected final boolean countUnknownPacket()
|
||||
{
|
||||
unknownPackets++;
|
||||
|
||||
final long tick = System.currentTimeMillis();
|
||||
if ((tick - _unknownPacketStartTick) > 60000)
|
||||
{
|
||||
_unknownPacketStartTick = tick;
|
||||
_unknownPacketsInMin = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
_unknownPacketsInMin++;
|
||||
return _unknownPacketsInMin > Config.CLIENT_PACKET_QUEUE_MAX_UNKNOWN_PER_MIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts burst length.
|
||||
* @param count - current number of processed packets in burst
|
||||
* @return true if execution of the queue need to be aborted.
|
||||
*/
|
||||
protected final boolean countBurst(int count)
|
||||
{
|
||||
if (count > maxBurstSize)
|
||||
{
|
||||
maxBurstSize = count;
|
||||
}
|
||||
|
||||
if (count < Config.CLIENT_PACKET_QUEUE_MAX_BURST_SIZE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
totalBursts++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts queue overflows.
|
||||
* @return true if threshold is reached.
|
||||
*/
|
||||
protected final boolean countQueueOverflow()
|
||||
{
|
||||
_queueOverflowDetected = true;
|
||||
totalQueueOverflows++;
|
||||
|
||||
final long tick = System.currentTimeMillis();
|
||||
if ((tick - _overflowStartTick) > 60000)
|
||||
{
|
||||
_overflowStartTick = tick;
|
||||
_overflowsInMin = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
_overflowsInMin++;
|
||||
return _overflowsInMin > Config.CLIENT_PACKET_QUEUE_MAX_OVERFLOWS_PER_MIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts underflow exceptions.
|
||||
* @return true if threshold is reached.
|
||||
*/
|
||||
protected final boolean countUnderflowException()
|
||||
{
|
||||
totalUnderflowExceptions++;
|
||||
|
||||
final long tick = System.currentTimeMillis();
|
||||
if ((tick - _underflowReadStartTick) > 60000)
|
||||
{
|
||||
_underflowReadStartTick = tick;
|
||||
_underflowReadsInMin = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
_underflowReadsInMin++;
|
||||
return _underflowReadsInMin > Config.CLIENT_PACKET_QUEUE_MAX_UNDERFLOWS_PER_MIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if maximum number of floods per minute is reached.
|
||||
*/
|
||||
protected final boolean countFloods()
|
||||
{
|
||||
return _floodsInMin > Config.CLIENT_PACKET_QUEUE_MAX_FLOODS_PER_MIN;
|
||||
}
|
||||
|
||||
private final boolean longFloodDetected()
|
||||
{
|
||||
return (_totalCount / BUFFER_SIZE) > Config.CLIENT_PACKET_QUEUE_MAX_AVERAGE_PACKETS_PER_SECOND;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if flood detected first and ActionFailed packet need to be sent. Later during flood returns true (and send ActionFailed) once per second.
|
||||
*/
|
||||
private final synchronized boolean countPacket()
|
||||
{
|
||||
_totalCount++;
|
||||
final long tick = System.currentTimeMillis();
|
||||
if ((tick - _packetCountStartTick) > 1000)
|
||||
{
|
||||
_packetCountStartTick = tick;
|
||||
|
||||
// clear flag if no more flooding during last seconds
|
||||
if (_floodDetected && !longFloodDetected() && (_packetsInSecond[_head] < (Config.CLIENT_PACKET_QUEUE_MAX_PACKETS_PER_SECOND / 2)))
|
||||
{
|
||||
_floodDetected = false;
|
||||
}
|
||||
|
||||
// wrap head of the buffer around the tail
|
||||
if (_head <= 0)
|
||||
{
|
||||
_head = BUFFER_SIZE;
|
||||
}
|
||||
_head--;
|
||||
|
||||
_totalCount -= _packetsInSecond[_head];
|
||||
_packetsInSecond[_head] = 1;
|
||||
return _floodDetected;
|
||||
}
|
||||
|
||||
final int count = ++_packetsInSecond[_head];
|
||||
if (!_floodDetected)
|
||||
{
|
||||
if (count > Config.CLIENT_PACKET_QUEUE_MAX_PACKETS_PER_SECOND)
|
||||
{
|
||||
shortFloods++;
|
||||
}
|
||||
else if (longFloodDetected())
|
||||
{
|
||||
longFloods++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_floodDetected = true;
|
||||
if ((tick - _floodStartTick) > 60000)
|
||||
{
|
||||
_floodStartTick = tick;
|
||||
_floodsInMin = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_floodsInMin++;
|
||||
}
|
||||
|
||||
return true; // Return true only in the beginning of the flood
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -74,42 +74,26 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
IN_GAME
|
||||
}
|
||||
|
||||
// floodprotectors
|
||||
private final FloodProtectors _floodProtectors = new FloodProtectors(this);
|
||||
|
||||
public GameClientState _state;
|
||||
|
||||
// Info
|
||||
public String _accountName;
|
||||
public SessionKey _sessionId;
|
||||
public PlayerInstance _player;
|
||||
private final ReentrantLock _playerLock = new ReentrantLock();
|
||||
|
||||
private boolean _isAuthedGG;
|
||||
private final long _connectionStartTime;
|
||||
private final List<Integer> _charSlotMapping = new ArrayList<>();
|
||||
|
||||
protected ScheduledFuture<?> _cleanupTask = null;
|
||||
|
||||
private final ClientStats _stats;
|
||||
|
||||
// Crypt
|
||||
private final GameCrypt _crypt;
|
||||
|
||||
private boolean _isDetached = false;
|
||||
|
||||
private final ArrayBlockingQueue<ReceivablePacket<GameClient>> _packetQueue;
|
||||
private final ReentrantLock _queueLock = new ReentrantLock();
|
||||
|
||||
private final ArrayBlockingQueue<ReceivablePacket<GameClient>> _packetQueue;
|
||||
private final GameCrypt _crypt;
|
||||
private GameClientState _state;
|
||||
private String _accountName;
|
||||
private SessionKey _sessionId;
|
||||
private PlayerInstance _player;
|
||||
private ScheduledFuture<?> _cleanupTask = null;
|
||||
private volatile boolean _isDetached = false;
|
||||
private boolean _isAuthedGG;
|
||||
private int _protocolVersion;
|
||||
|
||||
public GameClient(MMOConnection<GameClient> con)
|
||||
{
|
||||
super(con);
|
||||
_state = GameClientState.CONNECTED;
|
||||
_connectionStartTime = System.currentTimeMillis();
|
||||
_crypt = new GameCrypt();
|
||||
_stats = new ClientStats();
|
||||
_packetQueue = new ArrayBlockingQueue<>(Config.CLIENT_PACKET_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
@@ -134,16 +118,6 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
}
|
||||
}
|
||||
|
||||
public ClientStats getStats()
|
||||
{
|
||||
return _stats;
|
||||
}
|
||||
|
||||
public long getConnectionStartTime()
|
||||
{
|
||||
return _connectionStartTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decrypt(ByteBuffer buf, int size)
|
||||
{
|
||||
@@ -800,7 +774,7 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false if client can receive packets. True if detached, or flood detected, or queue overflow detected and queue still not empty.
|
||||
* Returns false if client can receive packets. True if detached or queue overflow detected and queue still not empty.
|
||||
* @return
|
||||
*/
|
||||
public boolean dropPacket()
|
||||
@@ -808,49 +782,15 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
return _isDetached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts buffer underflow exceptions.
|
||||
*/
|
||||
public void onBufferUnderflow()
|
||||
{
|
||||
if (_stats.countUnderflowException())
|
||||
{
|
||||
LOGGER.warning("Client " + this + " - Disconnected: Too many buffer underflow exceptions.");
|
||||
closeNow();
|
||||
return;
|
||||
}
|
||||
if (_state == GameClientState.CONNECTED) // in CONNECTED state kick client immediately
|
||||
{
|
||||
LOGGER.warning("Client " + this + " - Disconnected, too many buffer underflows in non-authed state.");
|
||||
closeNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add packet to the queue and start worker thread if needed
|
||||
* @param packet
|
||||
*/
|
||||
public void execute(ReceivablePacket<GameClient> packet)
|
||||
{
|
||||
if (_stats.countFloods())
|
||||
{
|
||||
LOGGER.warning("Client " + this + " - Disconnected, too many floods:" + _stats.longFloods + " long and " + _stats.shortFloods + " short.");
|
||||
closeNow();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_packetQueue.offer(packet))
|
||||
{
|
||||
if (_stats.countQueueOverflow())
|
||||
{
|
||||
LOGGER.warning("Client " + this + " - Disconnected, too many queue overflows.");
|
||||
closeNow();
|
||||
}
|
||||
else
|
||||
{
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -861,21 +801,7 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
|
||||
try
|
||||
{
|
||||
if (_state == GameClientState.CONNECTED)
|
||||
{
|
||||
if (_stats.processedPackets > 3)
|
||||
{
|
||||
LOGGER.warning("Client " + this + " - Disconnected, too many packets in non-authed state.");
|
||||
closeNow();
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadPool.execute(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThreadPool.execute(this);
|
||||
}
|
||||
ThreadPool.execute(this);
|
||||
}
|
||||
catch (RejectedExecutionException e)
|
||||
{
|
||||
@@ -892,7 +818,6 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
|
||||
try
|
||||
{
|
||||
int count = 0;
|
||||
while (true)
|
||||
{
|
||||
final ReceivablePacket<GameClient> packet = _packetQueue.poll();
|
||||
@@ -915,12 +840,6 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
|
||||
{
|
||||
LOGGER.warning("Exception during execution " + packet.getClass().getSimpleName() + ", client: " + this + "," + e.getMessage());
|
||||
}
|
||||
|
||||
count++;
|
||||
if (_stats.countBurst(count))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package org.l2jmobius.gameserver.network.clientpackets;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.l2jmobius.commons.mmocore.ReceivablePacket;
|
||||
@@ -42,10 +41,6 @@ public abstract class GameClientPacket extends ReceivablePacket<GameClient>
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.severe("Client: " + getClient() + " - Failed reading: " + getType() + " ; " + e.getMessage() + " " + e);
|
||||
if (e instanceof BufferUnderflowException)
|
||||
{
|
||||
getClient().onBufferUnderflow();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user