diff options
-rw-r--r-- | docs/inspircd.conf.example | 21 | ||||
-rw-r--r-- | include/users.h | 9 | ||||
-rw-r--r-- | src/inspircd.cpp | 76 | ||||
-rw-r--r-- | src/users.cpp | 8 |
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(); |