]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Made xline notices neater when notifying of unknown connections
[user/henk/code/inspircd.git] / src / inspircd.cpp
index 4fa04e3c0e025e1eba3f43db0ad7ac66de6878cf..b1aedde73132f856334235d52ce0967fff4b1969 100644 (file)
@@ -728,9 +728,9 @@ void WriteChannelLocal(chanrec* Ptr, userrec* user, char* text, ...)
 }
 
 
-void WriteChannelWithServ(char* ServName, chanrec* Ptr, userrec* user, char* text, ...)
+void WriteChannelWithServ(char* ServName, chanrec* Ptr, char* text, ...)
 {
-       if ((!Ptr) || (!user) || (!text))
+       if ((!Ptr) || (!text))
        {
                log(DEFAULT,"*** BUG *** WriteChannelWithServ was given an invalid parameter");
                return;
@@ -821,7 +821,8 @@ void WriteCommon(userrec *u, char* text, ...)
        vsnprintf(textbuffer, MAXBUF, text, argsPtr);
        va_end(argsPtr);
 
-       WriteFrom(u->fd,u,"%s",textbuffer);
+       // FIX: Stops a message going to the same person more than once
+       std::vector<int> already_sent;
 
         for (int i = 0; i < MAXCHANS; i++)
         {
@@ -832,10 +833,29 @@ void WriteCommon(userrec *u, char* text, ...)
                         {
                                 char* o = (*ulist)[j];
                                 userrec* otheruser = (userrec*)o;
-                                WriteFrom(otheruser->fd,u,"%s",textbuffer);
+                               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)
+                               {
+                                       already_sent.push_back(otheruser->fd);
+                                       WriteFrom(otheruser->fd,u,"%s",textbuffer);
+                               }
                         }
                 }
         }
+       // 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())
+       {
+               WriteFrom(u->fd,u,"%s",textbuffer);
+       }
 }
 
 /* write a formatted string to all users who share at least one common
@@ -860,6 +880,8 @@ void WriteCommonExcept(userrec *u, char* text, ...)
        vsnprintf(textbuffer, MAXBUF, text, argsPtr);
        va_end(argsPtr);
 
+       std::vector<int> already_sent;
+
         for (int i = 0; i < MAXCHANS; i++)
         {
                 if (u->chans[i].channel)
@@ -870,7 +892,22 @@ void WriteCommonExcept(userrec *u, char* text, ...)
                                 char* o = (*ulist)[j];
                                 userrec* otheruser = (userrec*)o;
                                if (u != otheruser)
-                                       WriteFrom(otheruser->fd,u,"%s",textbuffer);
+                               {
+                                       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)
+                                       {
+                                               already_sent.push_back(otheruser->fd);
+                                               WriteFrom(otheruser->fd,u,"%s",textbuffer);
+                                       }
+                               }
                         }
                 }
         }
@@ -2083,6 +2120,10 @@ void kill_link(userrec *user,const char* r)
                AddWhoWas(user);
        }
 
+        if (user->registered == 7) {
+                purge_empty_chans(user);
+        }
+
        if (iter != clientlist.end())
        {
                log(DEBUG,"deleting user hash value %lu",(unsigned long)iter->second);
@@ -2091,11 +2132,6 @@ void kill_link(userrec *user,const char* r)
                }
                clientlist.erase(iter);
        }
-
-       if (user->registered == 7) {
-               purge_empty_chans(user);
-       }
-       //user = NULL;
 }
 
 void kill_link_silent(userrec *user,const char* r)
@@ -2133,6 +2169,10 @@ void kill_link_silent(userrec *user,const char* r)
                 shutdown(user->fd,2);
                 close(user->fd);
         }
+
+        if (user->registered == 7) {
+                purge_empty_chans(user);
+        }
        
        if (iter != clientlist.end())
        {
@@ -2142,10 +2182,6 @@ void kill_link_silent(userrec *user,const char* r)
                }
                clientlist.erase(iter);
        }
-
-       if (user->registered == 7) {
-               purge_empty_chans(user);
-       }
 }
 
 
@@ -2648,18 +2684,45 @@ void ConnectUser(userrec *user)
        }
 }
 
-void handle_version(char **parameters, int pcnt, userrec *user)
+std::string GetVersionString()
 {
-       char Revision[] = "$Revision$";
+        char Revision[] = "$Revision$";
+       char versiondata[MAXBUF];
+        char *s1 = Revision;
+        char *savept;
+        char *v2 = strtok_r(s1," ",&savept);
+        s1 = savept;
+        v2 = strtok_r(s1," ",&savept);
+        s1 = savept;
+       snprintf(versiondata,MAXBUF,"%s Rev. %s %s :%s (O=%lu)",VERSION,v2,ServerName,SYSTEM,(unsigned long)OPTIMISATION);
+       return versiondata;
+}
 
-       char *s1 = Revision;
-       char *savept;
-       char *v2 = strtok_r(s1," ",&savept);
-       s1 = savept;
-       v2 = strtok_r(s1," ",&savept);
-       s1 = savept;
-       
-       WriteServ(user->fd,"351 %s :%s Rev. %s %s :%s (O=%lu)",user->nick,VERSION,v2,ServerName,SYSTEM,(unsigned long)OPTIMISATION);
+void handle_version(char **parameters, int pcnt, userrec *user)
+{
+       if (!pcnt)
+       {
+               WriteServ(user->fd,"351 %s :%s",user->nick,GetVersionString().c_str());
+       }
+       else
+       {
+                for (int j = 0; j < 32; j++)
+                {
+                        if (me[j] != NULL)
+                        {
+                                for (int x = 0; x < me[j]->connectors.size(); x++)
+                                {
+                                        if (match(me[j]->connectors[x].GetServerName().c_str(),parameters[0]))
+                                        {
+                                               WriteServ(user->fd,"351 %s :%s",user->nick,me[j]->connectors[x].GetVersionString().c_str());
+                                               return;
+                                       }
+                               }
+                       }
+               }
+               WriteServ(user->fd,"402 %s %s :No such server",user->nick,parameters[0]);
+       }
+       return;
 }
 
 
@@ -3000,8 +3063,6 @@ void process_command(userrec *user, char* cmd)
                {
                        if (strlen(command)>=(strlen(cmdlist[i].command))) if (!strncmp(command, cmdlist[i].command,MAXCOMMAND))
                        {
-                               log(DEBUG,"Found matching command");
-
                                if (parameters)
                                {
                                        if (parameters[0])
@@ -3022,8 +3083,6 @@ void process_command(userrec *user, char* cmd)
                                
                                if (user)
                                {
-                                       log(DEBUG,"Processing command");
-                                       
                                        /* activity resets the ping pending timer */
                                        user->nping = TIME + user->pingmax;
                                        if ((items) < cmdlist[i].min_params)
@@ -3077,7 +3136,6 @@ void process_command(userrec *user, char* cmd)
                                        }
                                        if ((user->registered == 7) || (!strncmp(command,"USER",4)) || (!strncmp(command,"NICK",4)) || (!strncmp(command,"PASS",4)))
                                        {
-                                               log(DEBUG,"process_command: handler: %s %s %lu",user->nick,command,(unsigned long)items);
                                                if (cmdlist[i].handler_function)
                                                {
                                                        
@@ -3111,7 +3169,6 @@ void process_command(userrec *user, char* cmd)
                                        }
                                        else
                                        {
-                                               log(DEBUG,"process_command: not registered: %s %s",user->nick,command);
                                                WriteServ(user->fd,"451 %s :You have not registered",command);
                                                return;
                                        }
@@ -3122,7 +3179,6 @@ void process_command(userrec *user, char* cmd)
        }
        if ((!cmd_found) && (user))
        {
-               log(DEBUG,"process_command: not in table: %s %s",user->nick,command);
                WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
        }
 }
@@ -3264,7 +3320,7 @@ void process_buffer(const char* cmdbuf,userrec *user)
        {
                return;
        }
-        log(DEBUG,"InspIRCd: processing: %s %s",user->nick,cmd);
+        log(DEBUG,"CMDIN: %s %s",user->nick,cmd);
        tidystring(cmd);
        if ((user) && (cmd))
        {
@@ -3282,6 +3338,30 @@ void DoSync(serverrec* serv, char* tcp_host)
        snprintf(data,MAXBUF,"Y %lu",(unsigned long)TIME);
        serv->SendPacket(data,tcp_host);
        // send users and channels
+
+       NetSendMyRoutingTable();
+
+       // send all routing table and uline voodoo. The ordering of these commands is IMPORTANT!
+        for (int j = 0; j < 32; j++)
+        {
+                if (me[j] != NULL)
+                {
+                        for (int k = 0; k < me[j]->connectors.size(); k++)
+                        {
+                                if (is_uline(me[j]->connectors[k].GetServerName().c_str()))
+                                {
+                                        snprintf(data,MAXBUF,"H %s",me[j]->connectors[k].GetServerName().c_str());
+                                        serv->SendPacket(data,tcp_host);
+                                }
+                        }
+                }
+        }
+
+       // send our version for the remote side to cache
+       snprintf(data,MAXBUF,"v %s %s",ServerName,GetVersionString().c_str());
+       serv->SendPacket(data,tcp_host);
+
+       // sync the users and channels, give the modules a look-in.
        for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
        {
                snprintf(data,MAXBUF,"N %lu %s %s %s %s +%s %s %s :%s",(unsigned long)u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,u->second->ip,u->second->server,u->second->fullname);
@@ -3337,22 +3417,6 @@ void DoSync(serverrec* serv, char* tcp_host)
        // sync global zlines, glines, etc
        sync_xlines(serv,tcp_host);
 
-       for (int j = 0; j < 32; j++)
-       {
-               if (me[j] != NULL)
-               {
-                       for (int k = 0; k < me[j]->connectors.size(); k++)
-                       {
-                               if (is_uline(me[j]->connectors[k].GetServerName().c_str()))
-                               {
-                                       snprintf(data,MAXBUF,"H %s",me[j]->connectors[k].GetServerName().c_str());
-                                       serv->SendPacket(data,tcp_host);
-                                       NetSendMyRoutingTable();
-                               }
-                       }
-               }
-       }
-
        snprintf(data,MAXBUF,"F %lu",(unsigned long)TIME);
        serv->SendPacket(data,tcp_host);
        log(DEBUG,"Sent sync");
@@ -3559,7 +3623,6 @@ bool DirValid(char* dirandfile)
                }
                work[p--] = '\0';
        }
-       log(DEBUG,"Dir valid: %s",work);
        char buffer[MAXBUF], otherdir[MAXBUF];
        // Get the current working directory
        if( getcwd( buffer, MAXBUF ) == NULL )
@@ -3568,17 +3631,13 @@ bool DirValid(char* dirandfile)
        if( getcwd( otherdir, MAXBUF ) == NULL )
                return false;
        chdir(buffer);
-       log(DEBUG,"Dir is really: %s",otherdir);
        if (strlen(otherdir) >= strlen(work))
        {
                otherdir[strlen(work)] = '\0';
-               log(DEBUG,"Compare: '%s' -> '%s'",otherdir,work);
                if (!strcmp(otherdir,work))
                {
-                       log(DEBUG,"Match ok");
                        return true;
                }
-               log(DEBUG,"No match");
                return false;
        }
        else return false;
@@ -3659,8 +3718,7 @@ int InspIRCd(void)
                Exit(ERROR);
        }
 
-       log(DEBUG,"InspIRCd: startup: begin");
-       log(DEBUG,"$Id$");
+       log(DEFAULT,"$Id$");
        if (geteuid() == 0)
        {
                printf("WARNING!!! You are running an irc server as ROOT!!! DO NOT DO THIS!!!\n\n");
@@ -3731,12 +3789,12 @@ int InspIRCd(void)
                printf("Loading module... \033[1;32m%s\033[0m\n",configToken);
                if (!LoadModule(configToken))
                {
-                       log(DEBUG,"Exiting due to a module loader error.");
+                       log(DEFAULT,"Exiting due to a module loader error.");
                        printf("\nThere was an error loading a module: %s\n\nYou might want to do './inspircd start' instead of 'bin/inspircd'\n\n",ModuleError());
                        Exit(0);
                }
        }
-       log(DEBUG,"Total loaded modules: %lu",(unsigned long)MODCOUNT+1);
+       log(DEFAULT,"Total loaded modules: %lu",(unsigned long)MODCOUNT+1);
        
        startup_time = time(NULL);
          
@@ -3801,14 +3859,14 @@ int InspIRCd(void)
 
         fd_set serverfds;
         timeval tvs;
-        tvs.tv_usec = 7000L;
+        tvs.tv_usec = 10000L;
         tvs.tv_sec = 0;
        tv.tv_sec = 0;
-       tv.tv_usec = 7000L;
-        char data[10240];
+       tv.tv_usec = 10000L;
+        char data[65535];
        timeval tval;
        fd_set sfd;
-        tval.tv_usec = 7000L;
+        tval.tv_usec = 10000L;
         tval.tv_sec = 0;
         int total_in_this_set = 0;
        int v = 0;
@@ -3852,7 +3910,7 @@ int InspIRCd(void)
                
                // serverFds timevals went here
                
-               tvs.tv_usec = 7000L;
+               tvs.tv_usec = 30000L;
                tvs.tv_sec = 0;
                int servresult = select(32767, &serverfds, NULL, NULL, &tvs);
                if (servresult > 0)
@@ -3879,7 +3937,7 @@ int InspIRCd(void)
                        }
                }
      
-               for (int cycle = 0; cycle < 4; cycle++) for (int x = 0; x < UDPportCount; x++)
+               for (int x = 0; x < UDPportCount; x++)
                {
                        std::deque<std::string> msgs;
                        msgs.clear();
@@ -3992,7 +4050,7 @@ int InspIRCd(void)
 
                        // tvals defined here
 
-                       tval.tv_usec = 7000L;
+                       tval.tv_usec = 1000L;
                        selectResult2 = select(65535, &sfd, NULL, NULL, &tval);
                        
                        // now loop through all of the items in this pool if any are waiting
@@ -4007,9 +4065,7 @@ int InspIRCd(void)
                                result = EAGAIN;
                                if ((count2a->second->fd != FD_MAGIC_NUMBER) && (count2a->second->fd != -1) && (FD_ISSET (count2a->second->fd, &sfd)))
                                {
-                                       memset(data, 0, 10240);
-                                       result = read(count2a->second->fd, data, 10240);
-                                       
+                                       result = read(count2a->second->fd, data, 65535);
                                        if (result)
                                        {
                                                // perform a check on the raw buffer as an array (not a string!) to remove
@@ -4020,40 +4076,53 @@ int InspIRCd(void)
                                                        if ((data[checker] == 0) || (data[checker] == 7))
                                                                data[checker] = ' ';
                                                }
+                                               if (result > 0)
+                                                       data[result] = '\0';
                                                userrec* current = count2a->second;
                                                int currfd = current->fd;
-                                               char* l = strtok(data,"\n");
                                                int floodlines = 0;
-                                               while (l)
+                                               current->AddBuffer(data);
+                                               if (current->recvq.length() > NetBufferSize)
                                                {
-                                                       floodlines++;
-                                                       if ((floodlines > current->flood) && (current->flood != 0))
+                                                       if (current->registered == 7)
                                                        {
-                                                               log(DEFAULT,"Excess flood from: %s!%s@%s",current->nick,current->ident,current->host);
-                                                               WriteOpers("*** Excess flood from: %s!%s@%s",current->nick,current->ident,current->host);
-                                                               kill_link(current,"Excess flood");
-                                                               goto label;
+                                                               kill_link(current,"RecvQ exceeded");
+                                                       }
+                                                       else
+                                                       {
+                                                               add_zline(120,ServerName,"Flood from unregistered connection",current->ip);
+                                                               apply_lines();
                                                        }
-                                                       char sanitized[NetBufferSize];
-                                                       memset(sanitized, 0, NetBufferSize);
-                                                       int ptt = 0;
-                                                       for (int pt = 0; pt < strlen(l); pt++)
+                                                       goto label;
+                                               }
+                                               // while there are complete lines to process...
+                                               while (current->BufferIsReady())
+                                               {
+                                                       floodlines++;
+                                                       if ((floodlines > current->flood) && (current->flood != 0))
                                                        {
-                                                               if (l[pt] != '\r')
+                                                               if (current->registered == 7)
+                                                               {
+                                                                       log(DEFAULT,"Excess flood from: %s!%s@%s",current->nick,current->ident,current->host);
+                                                                       WriteOpers("*** Excess flood from: %s!%s@%s",current->nick,current->ident,current->host);
+                                                                       kill_link(current,"Excess flood");
+                                                               }
+                                                               else
                                                                {
-                                                                       sanitized[ptt++] = l[pt];
+                                                                       add_zline(120,ServerName,"Flood from unregistered connection",current->ip);
+                                                                       apply_lines();
                                                                }
+                                                               goto label;
                                                        }
-                                                       sanitized[ptt] = '\0';
+                                                       char sanitized[MAXBUF];
+                                                       // use GetBuffer to copy single lines into the sanitized string
+                                                       strlcpy(sanitized,current->GetBuffer().c_str(),MAXBUF);
                                                        if (*sanitized)
                                                        {
-
-
                                                                // we're gonna re-scan to check if the nick is gone, after every
                                                                // command - if it has, we're gonna bail
                                                                bool find_again = false;
                                                                process_buffer(sanitized,current);
-       
                                                                // look for the user's record in case it's changed
                                                                for (user_hash::iterator c2 = clientlist.begin(); c2 != clientlist.end(); c2++)
                                                                {
@@ -4069,7 +4138,6 @@ int InspIRCd(void)
                                                                        goto label;
 
                                                        }
-                                                       l = strtok(NULL,"\n");
                                                }
                                                goto label;
                                        }
@@ -4104,13 +4172,13 @@ int InspIRCd(void)
                }
                for (int q = 0; q < total_in_this_set; q++)
                {
-                       // there is no iterator += operator :(
-                       //if (count2 != clientlist.end())
-                       //{
-                               count2++;
-                       //}
+                       count2++;
                }
        }
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+        sched_yield();
+#endif
        
        // set up select call
        for (count = 0; count < boundPortCount; count++)
@@ -4118,7 +4186,7 @@ int InspIRCd(void)
                FD_SET (openSockfd[count], &selectFds);
        }
 
-       tv.tv_usec = 7000L;
+       tv.tv_usec = 30000L;
        selectResult = select(MAXSOCKS, &selectFds, NULL, NULL, &tv);
 
        /* select is reporting a waiting socket. Poll them all to find out which */
@@ -4151,6 +4219,9 @@ int InspIRCd(void)
        }
        label:
        if (0) {};
+#ifdef _POSIX_PRIORITY_SCHEDULING
+        sched_yield();
+#endif
 }
 /* not reached */
 close (incomingSockfd);