chat flood protection (yet untested)

This commit is contained in:
Max-Wilhelm Bruker 2011-03-02 19:39:38 +01:00
parent 3bb1d9a1de
commit 6145d6d524
8 changed files with 49 additions and 1 deletions

View file

@ -268,6 +268,7 @@ void ProtocolResponse::initializeHash()
responseHash.insert("user_level_too_low", RespUserLevelTooLow);
responseHash.insert("in_ignore_list", RespInIgnoreList);
responseHash.insert("would_overwrite_old_session", RespWouldOverwriteOldSession);
responseHash.insert("chat_flood", RespChatFlood);
}
Response_JoinRoom::Response_JoinRoom(int _cmdId, ResponseCode _responseCode, ServerInfo_Room *_roomInfo)

View file

@ -8,7 +8,7 @@
class DeckList;
enum ResponseCode { RespNothing, RespOk, RespInternalError, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow, RespInIgnoreList, RespWouldOverwriteOldSession };
enum ResponseCode { RespNothing, RespOk, RespInternalError, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow, RespInIgnoreList, RespWouldOverwriteOldSession, RespChatFlood };
// PrivateZone: Contents of the zone are always visible to the owner,
// but not to anyone else.

View file

@ -38,6 +38,9 @@ public:
virtual bool getGameShouldPing() const = 0;
virtual int getMaxGameInactivityTime() const = 0;
virtual int getMaxPlayerInactivityTime() const = 0;
virtual int getMessageCountingInterval() const { return 0; }
virtual int getMaxMessageCountPerInterval() const { return 0; }
virtual int getMaxMessageSizePerInterval() const { return 0; }
virtual QMap<QString, ServerInfo_User *> getBuddyList(const QString &name) = 0;
virtual QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name) = 0;

View file

@ -208,6 +208,16 @@ void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont)
void Server_ProtocolHandler::pingClockTimeout()
{
int interval = server->getMessageCountingInterval();
if (interval > 0) {
messageSizeOverTime.prepend(0);
if (messageSizeOverTime.size() > server->getMessageCountingInterval())
messageSizeOverTime.removeLast();
messageCountOverTime.prepend(0);
if (messageCountOverTime.size() > server->getMessageCountingInterval())
messageCountOverTime.removeLast();
}
if (lastCommandTime.secsTo(QDateTime::currentDateTime()) > server->getMaxPlayerInactivityTime())
deleteLater();
}
@ -355,6 +365,26 @@ ResponseCode Server_ProtocolHandler::cmdLeaveRoom(Command_LeaveRoom * /*cmd*/, C
ResponseCode Server_ProtocolHandler::cmdRoomSay(Command_RoomSay *cmd, CommandContainer * /*cont*/, Server_Room *room)
{
QString msg = cmd->getMessage();
if (server->getMessageCountingInterval() > 0) {
int totalSize = 0, totalCount = 0;
if (messageSizeOverTime.isEmpty())
messageSizeOverTime.prepend(0);
messageSizeOverTime[0] += msg.size();
for (int i = 0; i < messageSizeOverTime.size(); ++i)
totalSize += messageSizeOverTime[i];
if (messageCountOverTime.isEmpty())
messageCountOverTime.prepend(0);
++messageCountOverTime[0];
for (int i = 0; i < messageCountOverTime.size(); ++i)
totalCount += messageCountOverTime[i];
if ((totalSize > server->getMaxMessageSizePerInterval()) || (totalCount > server->getMaxMessageCountPerInterval()))
return RespChatFlood;
}
room->say(this, cmd->getMessage());
return RespOk;
}

View file

@ -30,6 +30,7 @@ protected:
QMap<QString, ServerInfo_User *> buddyList, ignoreList;
private:
QList<ProtocolItem *> itemQueue;
QList<int> messageSizeOverTime, messageCountOverTime;
QDateTime lastCommandTime;
QTimer *pingClock;

View file

@ -27,3 +27,8 @@ size=1
[game]
max_game_inactivity_time=120
max_player_inactivity_time=15
[security]
message_counting_interval=10
max_message_size_per_interval=1000
max_message_count_per_interval=10

View file

@ -84,6 +84,10 @@ Servatrice::Servatrice(QObject *parent)
maxGameInactivityTime = settings->value("game/max_game_inactivity_time").toInt();
maxPlayerInactivityTime = settings->value("game/max_player_inactivity_time").toInt();
messageCountingInterval = settings->value("security/message_counting_interval").toInt();
maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt();
maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt();
}
Servatrice::~Servatrice()

View file

@ -45,6 +45,9 @@ public:
bool getGameShouldPing() const { return true; }
int getMaxGameInactivityTime() const { return maxGameInactivityTime; }
int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; }
int getMessageCountingInterval() const { return messageCountingInterval; }
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
QString getDbPrefix() const { return dbPrefix; }
void updateLoginMessage();
ServerInfo_User *getUserData(const QString &name);
@ -62,6 +65,7 @@ private:
int uptime;
int maxGameInactivityTime;
int maxPlayerInactivityTime;
int messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval;
ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete);
};