summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/inspircd.conf.example21
-rw-r--r--include/users.h9
-rw-r--r--src/inspircd.cpp76
-rw-r--r--src/users.cpp8
4 files changed, 75 insertions, 39 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example
index 4e98838a7..c304cd5ce 100644
--- a/docs/inspircd.conf.example
+++ b/docs/inspircd.conf.example
@@ -107,6 +107,8 @@
# <connect allow="ip or host" password="blahblah"> #
# <connect allow="ip or host" password="blah" timeout="10"> #
# <connect allow="ip or host" timeout="blah" flood="5"> #
+# <connect allow="ip or host" threshold="8" pingfreq="120"> #
+# <connect allow="ip or host" sendq="99999"> #
# <connect deny="ip or host"> #
# #
# You may optionally include timeout="x" on any allow line, which #
@@ -116,11 +118,24 @@
# You may also optionally include a flood="x" line which indicates #
# the number of lines a user may place into their buffer at once #
# before they are disconnected for excess flood. The default is to #
-# DISABLE this feature. A recommended value is 10. #
-
+# DISABLE this feature. A recommended value is 10. A counter is #
+# maintained for each user which is reset every 'threshold' seconds #
+# and specifying this threshold value with threshold="X" indicates #
+# how often the counter is reset. For example, with flood="5" and #
+# threshold="8", the user may not send more than 5 lines in 8 secs. #
+# #
+# You may optionally specify the sendq size and ping frequency of #
+# each connect:allow line using the pingfreq="X" and sendq="X" #
+# settings as shown in the full example below. #
+# The ping frequency is specified in seconds, and the sendq size #
+# in bytes. It is recommended, although not enforced, that you #
+# should never set your sendq size to less than 8k. Send Queues are #
+# dynamically allocated and can grow as needed up to the maximum #
+# size specified. #
+# #
<connect allow="196.12.*" password="secret">
-<connect allow="*" timeout="60" flood="10">
+<connect allow="*" timeout="60" flood="10" timeout="60" pingfreq="120" sendq="131072">
<connect deny="69.254.*">
diff --git a/include/users.h b/include/users.h
index b747669c9..3e4afe88f 100644
--- a/include/users.h
+++ b/include/users.h
@@ -67,6 +67,10 @@ class ConnectClass : public classbase
/** Threshold value for flood disconnect
*/
long threshold;
+
+ /** Maximum size of sendq for users in this class
+ */
+ long sendqmax;
ConnectClass()
{
@@ -74,6 +78,7 @@ class ConnectClass : public classbase
flood = 0;
pingtime = 0;
threshold = 0;
+ sendqmax = 0;
strlcpy(host,"",MAXBUF);
strlcpy(pass,"",MAXBUF);
}
@@ -199,6 +204,10 @@ class userrec : public connection
*/
std::string WriteError;
+ /** Maximum size this user's sendq can become
+ */
+ long sendqmax;
+
userrec();
virtual ~userrec() { }
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index d5ba7f890..714ab6a8a 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -357,7 +357,7 @@ void readfile(file_cache &F, const char* fname)
void ReadConfig(bool bail, userrec* user)
{
char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF];
- char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF],DNT[MAXBUF],pfreq[MAXBUF],thold[MAXBUF];
+ char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF],DNT[MAXBUF],pfreq[MAXBUF],thold[MAXBUF],sqmax[MAXBUF];
ConnectClass c;
std::stringstream errstr;
@@ -463,6 +463,7 @@ void ReadConfig(bool bail, userrec* user)
ConfValue("connect","flood",i,flood,&config_f);
ConfValue("connect","pingfreq",i,pfreq,&config_f);
ConfValue("connect","threshold",i,thold,&config_f);
+ ConfValue("connect","sendq",i,sqmax,&config_f);
if (Value[0])
{
strlcpy(c.host,Value,MAXBUF);
@@ -474,10 +475,15 @@ void ReadConfig(bool bail, userrec* user)
c.pingtime = 120;
c.flood = atoi(flood);
c.threshold = 5;
+ c.sendqmax = 131072;
if (atoi(thold)>0)
{
c.threshold = atoi(thold);
}
+ if (atoi(sqmax)>0)
+ {
+ c.sendqmax = atoi(sqmax);
+ }
if (atoi(timeout)>0)
{
c.registration_timeout = atoi(timeout);
@@ -582,11 +588,15 @@ void ReadConfig(bool bail, userrec* user)
}
}
-/* write formatted text to a socket, in same format as printf */
+/* write formatted text to a socket, in same format as printf
+ * New in 1.0 Beta 5 - Nothing is written directly to a users fd any more.
+ * Instead, data builds up in the users sendq and each time around the mainloop
+ * this data is flushed to the user's socket (see userrec::FlushWriteBuf).
+ */
void Write(int sock,char *text, ...)
{
- if (sock == FD_MAGIC_NUMBER)
+ if (sock < 0)
return;
if (!text)
{
@@ -603,24 +613,21 @@ void Write(int sock,char *text, ...)
va_end(argsPtr);
int bytes = snprintf(tb,MAXBUF,"%s\r\n",textbuffer);
chop(tb);
- if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
+ if (fd_ref_table[sock])
{
- if (fd_ref_table[sock])
- {
- int MOD_RESULT = 0;
- FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
- fd_ref_table[sock]->AddWriteBuf(tb);
- statsSent += bytes;
- }
- else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
+ fd_ref_table[sock]->AddWriteBuf(tb);
+ statsSent += bytes;
}
+ else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
}
/* write a server formatted numeric response to a single socket */
void WriteServ(int sock, char* text, ...)
{
- if (sock == FD_MAGIC_NUMBER)
+ if (sock < 0)
return;
if (!text)
{
@@ -636,24 +643,21 @@ void WriteServ(int sock, char* text, ...)
va_end(argsPtr);
int bytes = snprintf(tb,MAXBUF,":%s %s\r\n",ServerName,textbuffer);
chop(tb);
- if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
- {
- if (fd_ref_table[sock])
- {
- int MOD_RESULT = 0;
- FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
- fd_ref_table[sock]->AddWriteBuf(tb);
- statsSent += bytes;
- }
- else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
- }
+ if (fd_ref_table[sock])
+ {
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
+ fd_ref_table[sock]->AddWriteBuf(tb);
+ statsSent += bytes;
+ }
+ else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
}
/* write text from an originating user to originating user */
void WriteFrom(int sock, userrec *user,char* text, ...)
{
- if (sock == FD_MAGIC_NUMBER)
+ if (sock < 0)
return;
if ((!text) || (!user))
{
@@ -669,17 +673,14 @@ void WriteFrom(int sock, userrec *user,char* text, ...)
va_end(argsPtr);
int bytes = snprintf(tb,MAXBUF,":%s!%s@%s %s\r\n",user->nick,user->ident,user->dhost,textbuffer);
chop(tb);
- if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
- {
- if (fd_ref_table[sock])
- {
- int MOD_RESULT = 0;
- FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
- fd_ref_table[sock]->AddWriteBuf(tb);
- statsSent += bytes;
- }
- else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
- }
+ if (fd_ref_table[sock])
+ {
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
+ fd_ref_table[sock]->AddWriteBuf(tb);
+ statsSent += bytes;
+ }
+ else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
}
/* write text to an destination user from a source user (e.g. user privmsg) */
@@ -2538,6 +2539,7 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip)
unsigned long class_regtimeout = 90;
int class_flood = 0;
long class_threshold = 5;
+ long class_sqmax = 131072; // 128kb
for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++)
{
@@ -2547,6 +2549,7 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip)
class_flood = i->flood;
clientlist[tempnick]->pingmax = i->pingtime;
class_threshold = i->threshold;
+ class_sqmax = i->sendqmax;
break;
}
}
@@ -2555,6 +2558,7 @@ void AddClient(int socket, char* host, int port, bool iscached, char* ip)
clientlist[tempnick]->timeout = TIME+class_regtimeout;
clientlist[tempnick]->flood = class_flood;
clientlist[tempnick]->threshold = class_threshold;
+ clientlist[tempnick]->sendqmax = class_sqmax;
for (int i = 0; i < MAXCHANS; i++)
{
diff --git a/src/users.cpp b/src/users.cpp
index 0e676600e..5154b04cb 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -220,6 +220,14 @@ std::string userrec::GetBuffer()
void userrec::AddWriteBuf(std::string data)
{
+ if (this->GetWriteError() != "")
+ return;
+ if (sendq.length() + data.length() > this->sendqmax)
+ {
+ WriteOpers("*** User %s SendQ of %d exceeds connect class maximum of %d",this->nick,sendq.length() + data.length(),sendq.length());
+ this->SetWriteError("SendQ exceeded");
+ return;
+ }
std::stringstream stream;
stream << sendq << data;
sendq = stream.str();