]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Extra safety checks to avoid trying to write() remote users
[user/henk/code/inspircd.git] / src / inspircd.cpp
index c3c3acb3ada53e369e058e6b5b9ff11dea1ab914..a9e0e316f5b3225932885f7a823dd7669ce20db1 100644 (file)
@@ -181,6 +181,8 @@ typedef std::deque<command_t> command_table;
 // by an integer, meaning there is no need for a scan/search operation.
 userrec* fd_ref_table[65536];
 
+int statsAccept = 0, statsRefused = 0, statsUnknown = 0, statsCollisions = 0, statsDns = 0, statsDnsGood = 0, statsDnsBad = 0, statsConnects = 0, statsSent= 0, statsRecv = 0;
+
 serverrec* me[32];
 
 FILE *log_file;
@@ -216,6 +218,8 @@ std::stringstream config_f(stringstream::in | stringstream::out);
 
 std::vector<userrec*> all_opers;
 
+static char already_sent[65536];
+
 void AddOper(userrec* user)
 {
        log(DEBUG,"Oper added to optimization list");
@@ -587,7 +591,7 @@ void Write(int sock,char *text, ...)
        va_end(argsPtr);
        int bytes = snprintf(tb,MAXBUF,"%s\r\n",textbuffer);
        chop(tb);
-       if (sock != -1)
+       if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
        {
                int MOD_RESULT = 0;
                FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes > 512 ? 512 : bytes));
@@ -598,6 +602,7 @@ void Write(int sock,char *text, ...)
                        fd_ref_table[sock]->bytes_out += (bytes > 512 ? 512 : bytes);
                        fd_ref_table[sock]->cmds_out++;
                }
+               statsSent += (bytes > 512 ? 512 : bytes);
        }
 }
 
@@ -620,7 +625,7 @@ 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)
+       if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
        {
                 int MOD_RESULT = 0;
                 FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes > 512 ? 512 : bytes));
@@ -631,6 +636,7 @@ void WriteServ(int sock, char* text, ...)
                         fd_ref_table[sock]->bytes_out += (bytes > 512 ? 512 : bytes);
                         fd_ref_table[sock]->cmds_out++;
                 }
+               statsSent += (bytes > 512 ? 512 : bytes);
        }
 }
 
@@ -653,7 +659,7 @@ 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)
+       if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
        {
                 int MOD_RESULT = 0;
                 FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes > 512 ? 512 : bytes));
@@ -664,6 +670,7 @@ void WriteFrom(int sock, userrec *user,char* text, ...)
                         fd_ref_table[sock]->bytes_out += (bytes > 512 ? 512 : bytes);
                         fd_ref_table[sock]->cmds_out++;
                 }
+               statsSent += (bytes > 512 ? 512 : bytes);
        }
 }
 
@@ -853,7 +860,9 @@ void WriteCommon(userrec *u, char* text, ...)
        va_end(argsPtr);
 
        // FIX: Stops a message going to the same person more than once
-       std::vector<int> already_sent;
+       bzero(&already_sent,65536);
+
+       bool sent_to_at_least_one = false;
 
         for (int i = 0; i < MAXCHANS; i++)
         {
@@ -864,26 +873,18 @@ void WriteCommon(userrec *u, char* text, ...)
                         {
                                 char* o = (*ulist)[j];
                                 userrec* otheruser = (userrec*)o;
-                               bool do_send = true;
-                               for (int t = 0; t < already_sent.size(); t++)
+                               if ((otheruser->fd > 0) && (!already_sent[otheruser->fd]))
                                {
-                                       if (already_sent[t] == otheruser->fd)
-                                       {
-                                               do_send = false;
-                                               break;
-                                       }
-                               }
-                               if (do_send)
-                               {
-                                       already_sent.push_back(otheruser->fd);
+                                       already_sent[otheruser->fd] = 1;
                                        WriteFrom(otheruser->fd,u,"%s",textbuffer);
+                                       sent_to_at_least_one = true;
                                }
                         }
                 }
         }
        // if the user was not in any channels, no users will receive the text. Make sure the user
        // receives their OWN message for WriteCommon
-       if (!already_sent.size())
+       if (!sent_to_at_least_one)
        {
                WriteFrom(u->fd,u,"%s",textbuffer);
        }
@@ -911,7 +912,7 @@ void WriteCommonExcept(userrec *u, char* text, ...)
        vsnprintf(textbuffer, MAXBUF, text, argsPtr);
        va_end(argsPtr);
 
-       std::vector<int> already_sent;
+        bzero(&already_sent,65536);
 
         for (int i = 0; i < MAXCHANS; i++)
         {
@@ -924,18 +925,9 @@ void WriteCommonExcept(userrec *u, char* text, ...)
                                 userrec* otheruser = (userrec*)o;
                                if (u != otheruser)
                                {
-                                       bool do_send = true;
-                                       for (int t = 0; t < already_sent.size(); t++)
-                                       {
-                                               if (already_sent[t] == otheruser->fd)
-                                               {
-                                                       do_send = false;
-                                                       break;
-                                               }
-                                       }
-                                       if (do_send)
+                                       if ((otheruser->fd > 0) && (!already_sent[otheruser->fd]))
                                        {
-                                               already_sent.push_back(otheruser->fd);
+                                               already_sent[otheruser->fd] = 1;
                                                WriteFrom(otheruser->fd,u,"%s",textbuffer);
                                        }
                                }
@@ -2688,7 +2680,7 @@ void ShowMOTD(userrec *user)
         WholeMOTD = WholeMOTD + std::string(":") + std::string(ServerName) + std::string(" 376 ") + std::string(user->nick) + std::string(" :End of message of the day.\r\n");
         // only one write operation
         send(user->fd,WholeMOTD.c_str(),WholeMOTD.length(),0);
-
+       statsSent += WholeMOTD.length();
 }
 
 void ShowRULES(userrec *user)
@@ -2709,6 +2701,7 @@ void ShowRULES(userrec *user)
 /* shows the message of the day, and any other on-logon stuff */
 void FullConnectUser(userrec* user)
 {
+       statsConnects++;
         user->registered = 7;
         user->idle_lastmsg = TIME;
         log(DEBUG,"ConnectUser: %s",user->nick);
@@ -2982,11 +2975,13 @@ void force_nickchange(userrec* user,const char* newnick)
 
        FOREACH_RESULT(OnUserPreNick(user,newnick));
        if (MOD_RESULT) {
+               statsCollisions++;
                kill_link(user,"Nickname collision");
                return;
        }
        if (matches_qline(newnick))
        {
+               statsCollisions++;
                kill_link(user,"Nickname collision");
                return;
        }
@@ -3193,6 +3188,7 @@ void process_command(userrec *user, char* cmd)
                        {
                                if (strchr("@!\"$%^&*(){}[]_=+;:'#~,<>/?\\|`",command[x]))
                                {
+                                       statsUnknown++;
                                        WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
                                        return;
                                }
@@ -3315,6 +3311,7 @@ void process_command(userrec *user, char* cmd)
        }
        if ((!cmd_found) && (user))
        {
+               statsUnknown++;
                WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
        }
 }
@@ -4128,6 +4125,9 @@ int InspIRCd(void)
 
                if ((curr) && (curr->fd != 0))
                {
+#ifdef _POSIX_PRIORITY_SCHEDULING
+        sched_yield();
+#endif
                        // assemble up to 64 sockets into an fd_set
                        // to implement a pooling mechanism.
                        //
@@ -4155,6 +4155,7 @@ int InspIRCd(void)
                                                {
                                                        log(DEBUG,"signon exceed, registered=3, and modules ready, OK");
                                                        curr->dns_done = true;
+                                                       statsDnsBad++;
                                                        FullConnectUser(curr);
                                                        goto label;
                                                }
@@ -4216,9 +4217,9 @@ int InspIRCd(void)
                                        }
                                        else result = result2;
                                        log(DEBUG,"Read result: %d",result);
-       
                                        if (result)
                                        {
+                                               statsRecv += result;
                                                // perform a check on the raw buffer as an array (not a string!) to remove
                                                // characters 0 and 7 which are illegal in the RFC - replace them with spaces.
                                                // hopefully this should stop even more people whining about "Unknown command: *"
@@ -4391,10 +4392,12 @@ int InspIRCd(void)
                                {
                                        WriteOpers("*** WARNING: Accept failed on port %lu (%s)",(unsigned long)ports[count],target);
                                        log(DEBUG,"InspIRCd: accept failed: %lu",(unsigned long)ports[count]);
+                                       statsRefused++;
                                }
                                else
                                {
                                        FOREACH_MOD OnRawSocketAccept(incomingSockfd, resolved, ports[count]);
+                                       statsAccept++;
                                        AddClient(incomingSockfd, resolved, ports[count], false, inet_ntoa (client.sin_addr));
                                        log(DEBUG,"InspIRCd: adding client on port %lu fd=%lu",(unsigned long)ports[count],(unsigned long)incomingSockfd);
                                }
@@ -4406,6 +4409,7 @@ int InspIRCd(void)
        if (0) {};
 #ifdef _POSIX_PRIORITY_SCHEDULING
         sched_yield();
+       sched_yield();
 #endif
 }
 /* not reached */