summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2007-10-21 14:08:13 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2007-10-21 14:08:13 +0000
commit6856c87ae51d655870607c6e74e0eed6d338283a (patch)
tree6b2036107b1bd0d884c5b3a7515d58cf960db334
parentfd37f4ba0e5196f2c8d0fa307622ed48c168274f (diff)
*untested* command buffering/penalty
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@8250 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/command_parse.h10
-rw-r--r--include/users.h12
-rw-r--r--src/command_parse.cpp75
-rw-r--r--src/userprocess.cpp43
-rw-r--r--src/users.cpp3
5 files changed, 89 insertions, 54 deletions
diff --git a/include/command_parse.h b/include/command_parse.h
index be18db4f9..d5c7049db 100644
--- a/include/command_parse.h
+++ b/include/command_parse.h
@@ -54,7 +54,7 @@ class CoreExport CommandParser : public classbase
* @param user The user to parse the command for
* @param cmd The command string to process
*/
- void ProcessCommand(User *user, std::string &cmd);
+ bool ProcessCommand(User *user, std::string &cmd);
/** Finds the init_command symbol in a .so file
* @param v A function pointer to be initialized
@@ -179,7 +179,13 @@ class CoreExport CommandParser : public classbase
* @param buffer The buffer line to process
* @param user The user to whom this line belongs
*/
- void ProcessBuffer(std::string &buffer,User *user);
+ bool ProcessBuffer(std::string &buffer,User *user);
+
+ /** Process lines in a users sendq.
+ * @param current The user to process
+ * @param one_only if one_only is set only one command is processed from the sendq.
+ */
+ void DoLines(User* current, bool one_only = false);
/** Remove all commands relating to module 'source'.
* @param source A module name which has introduced new commands
diff --git a/include/users.h b/include/users.h
index f43c787a0..d927890f0 100644
--- a/include/users.h
+++ b/include/users.h
@@ -681,12 +681,14 @@ class CoreExport User : public connection
*/
bool exempt;
- /** If this bool is set for a user, then the user is under penalty, in short they
- * are waiting for some held commands to be executed. If this is the case, then
- * any commands they have in their sendq are executed on a timer tick rather than in
- * their event handler.
+ /** This value contains how far into the penalty threshold the user is. Once its over
+ * the penalty threshold then commands are held and processed on-timer.
*/
- bool UnderPenalty;
+ int Penalty;
+
+ /** True if we are flushing penalty lines
+ */
+ bool OverPenalty;
/** If this bool is set then penalty rules do not apply to this user
*/
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index f07a4ffd7..f3ff69c96 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -6,7 +6,7 @@
* See: http://www.inspircd.org/wiki/index.php/Credits
*
* This program is free but copyrighted software; see
- * the file COPYING for details.
+ * the file COPYING for details.
*
* ---------------------------------------------------
*/
@@ -214,7 +214,45 @@ CmdResult CommandParser::CallHandler(const std::string &commandname,const char**
return CMD_INVALID;
}
-void CommandParser::ProcessCommand(User *user, std::string &cmd)
+void CommandParser::DoLines(User* current, bool one_only)
+{
+ // while there are complete lines to process...
+ int floodlines = 0;
+
+ while (current->BufferIsReady())
+ {
+ if (ServerInstance->Time() > current->reset_due)
+ {
+ current->reset_due = ServerInstance->Time() + current->threshold;
+ current->lines_in = 0;
+ }
+
+ if (++current->lines_in > current->flood && current->flood)
+ {
+ ServerInstance->FloodQuitUser(current);
+ return;
+ }
+
+ if ((++floodlines > current->flood) && (current->flood != 0))
+ {
+ ServerInstance->FloodQuitUser(current);
+ return;
+ }
+
+ // use GetBuffer to copy single lines into the sanitized string
+ std::string single_line = current->GetBuffer();
+ current->bytes_in += single_line.length();
+ current->cmds_in++;
+ if (single_line.length() > MAXBUF - 2) // MAXBUF is 514 to allow for neccessary line terminators
+ single_line.resize(MAXBUF - 2); // So to trim to 512 here, we use MAXBUF - 2
+
+ // ProcessBuffer returns false if the user has gone over penalty
+ if (!ServerInstance->Parser->ProcessBuffer(single_line, current) || one_only)
+ break;
+ }
+}
+
+bool CommandParser::ProcessCommand(User *user, std::string &cmd)
{
const char *command_p[MAXPARAMETERS];
int items = 0;
@@ -241,7 +279,7 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command,command_p,items,user,false,cmd));
if (MOD_RESULT == 1) {
- return;
+ return true;
}
if (!user)
@@ -251,7 +289,7 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
* I'm not entirely sure when we would be passed NULL, but let's handle it
* anyway, by dropping it like a hot potato. -- w00t
*/
- return;
+ return true;
}
/* find the command, check it exists */
@@ -261,9 +299,15 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
{
ServerInstance->stats->statsUnknown++;
user->WriteServ("421 %s %s :Unknown command",user->nick,command.c_str());
- return;
+ return true;
}
+ /* Modify the user's penalty */
+ user->Penalty += cm->second->Penalty;
+ bool do_more = (user->Penalty < 10);
+ if (do_more)
+ user->OverPenalty = true;
+
/* activity resets the ping pending timer */
user->nping = ServerInstance->Time() + user->pingmax;
if (cm->second->flags_needed)
@@ -271,12 +315,12 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
if (!user->IsModeSet(cm->second->flags_needed))
{
user->WriteServ("481 %s :Permission Denied - You do not have the required operator privileges",user->nick);
- return;
+ return do_more;
}
if (!user->HasPermission(command))
{
user->WriteServ("481 %s :Permission Denied - Oper type %s does not have access to command %s",user->nick,user->oper,command.c_str());
- return;
+ return do_more;
}
}
if ((user->registered == REG_ALL) && (!IS_OPER(user)) && (cm->second->IsDisabled()))
@@ -285,19 +329,19 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
user->WriteServ("421 %s %s :This command has been disabled.",user->nick,command.c_str());
ServerInstance->SNO->WriteToSnoMask('d', "%s denied for %s (%s@%s)",
command.c_str(), user->nick, user->ident, user->host);
- return;
+ return do_more;
}
if (items < cm->second->min_params)
{
user->WriteServ("461 %s %s :Not enough parameters.", user->nick, command.c_str());
if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (cm->second->syntax.length()))
user->WriteServ("304 %s :SYNTAX %s %s", user->nick, cm->second->command.c_str(), cm->second->syntax.c_str());
- return;
+ return do_more;
}
if ((user->registered != REG_ALL) && (!cm->second->WorksBeforeReg()))
{
user->WriteServ("451 %s :You have not registered",command.c_str());
- return;
+ return do_more;
}
else
{
@@ -309,7 +353,7 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command,command_p,items,user,true,cmd));
if (MOD_RESULT == 1)
- return;
+ return do_more;
/*
* WARNING: be careful, the user may be deleted soon
@@ -317,7 +361,7 @@ void CommandParser::ProcessCommand(User *user, std::string &cmd)
CmdResult result = cm->second->Handle(command_p,items,user);
FOREACH_MOD(I_OnPostCommand,OnPostCommand(command, command_p, items, user, result,cmd));
- return;
+ return do_more;
}
}
@@ -351,12 +395,12 @@ void CommandParser::RemoveCommand(Commandable::iterator safei, const char* sourc
}
}
-void CommandParser::ProcessBuffer(std::string &buffer,User *user)
+bool CommandParser::ProcessBuffer(std::string &buffer,User *user)
{
std::string::size_type a;
if (!user)
- return;
+ return true;
while ((a = buffer.rfind("\n")) != std::string::npos)
buffer.erase(a);
@@ -368,9 +412,10 @@ void CommandParser::ProcessBuffer(std::string &buffer,User *user)
if (!user->muted)
{
ServerInstance->Log(DEBUG,"C[%d] I :%s %s",user->GetFd(), user->nick, buffer.c_str());
- this->ProcessCommand(user,buffer);
+ return this->ProcessCommand(user,buffer);
}
}
+ return true;
}
bool CommandParser::CreateCommand(Command *f, void* so_handle)
diff --git a/src/userprocess.cpp b/src/userprocess.cpp
index 9009cf061..75f0da0ee 100644
--- a/src/userprocess.cpp
+++ b/src/userprocess.cpp
@@ -72,7 +72,6 @@ void ProcessUserHandler::Call(User* cu)
{
User *current;
int currfd;
- int floodlines = 0;
Server->stats->statsRecv += result;
/*
@@ -123,36 +122,7 @@ void ProcessUserHandler::Call(User* cu)
return;
}
- // while there are complete lines to process...
- while (current->BufferIsReady())
- {
- if (Server->Time() > current->reset_due)
- {
- current->reset_due = Server->Time() + current->threshold;
- current->lines_in = 0;
- }
-
- if (++current->lines_in > current->flood && current->flood)
- {
- Server->FloodQuitUser(current);
- return;
- }
-
- if ((++floodlines > current->flood) && (current->flood != 0))
- {
- Server->FloodQuitUser(current);
- return;
- }
-
- // use GetBuffer to copy single lines into the sanitized string
- std::string single_line = current->GetBuffer();
- current->bytes_in += single_line.length();
- current->cmds_in++;
- if (single_line.length() > MAXBUF - 2) /* MAXBUF is 514 to allow for neccessary line terminators */
- single_line.resize(MAXBUF - 2); /* So to trim to 512 here, we use MAXBUF - 2 */
-
- Server->Parser->ProcessBuffer(single_line, current);
- }
+ Server->Parser->DoLines(current);
return;
}
@@ -190,6 +160,17 @@ void InspIRCd::DoBackgroundUserStuff()
{
User *curr = *count2;
+ if (curr->OverPenalty)
+ Parser->DoLines(curr, true);
+
+ /* Knock a second off */
+ if (curr->Penalty)
+ {
+ curr->Penalty--;
+ if (!curr->Penalty)
+ curr->OverPenalty = false;
+ }
+
if ((curr->registered != REG_ALL) && (TIME > curr->timeout))
{
/*
diff --git a/src/users.cpp b/src/users.cpp
index f978fc441..060e90782 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -175,9 +175,10 @@ User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance
server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName);
reset_due = ServerInstance->Time();
age = ServerInstance->Time(true);
+ Penalty = 0;
lines_in = lastping = signon = idle_lastmsg = nping = registered = 0;
ChannelCount = timeout = flood = bytes_in = bytes_out = cmds_in = cmds_out = 0;
- ExemptFromPenalty = UnderPenalty = muted = exempt = haspassed = dns_done = false;
+ OverPenalty = ExemptFromPenalty = muted = exempt = haspassed = dns_done = false;
fd = -1;
recvq.clear();
sendq.clear();