From 16934ea87517d1b45419cadf2376a7da11a69b27 Mon Sep 17 00:00:00 2001 From: brain Date: Wed, 11 May 2005 23:47:09 +0000 Subject: added sendq stuff, see example config git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@1362 e03df62e-2008-0410-955e-edbf42e46eb7 --- docs/inspircd.conf.example | 21 +++++++++++-- include/users.h | 9 ++++++ src/inspircd.cpp | 76 ++++++++++++++++++++++++---------------------- 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 @@ # # # # # # +# # +# # # # # # # 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. # +# # - + 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(); -- cgit v1.2.3