]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/users.cpp
Fix the problems GreenReaper found with the windows select engine, this has never...
[user/henk/code/inspircd.git] / src / users.cpp
index 46665396f0300297613ac61fc3e95b5f8fd009cf..108ce138559dfb4b6a0d9e76fb000a824d7d9ed6 100644 (file)
 #include "bancache.h"
 #include "commands/cmd_whowas.h"
 
-static unsigned long already_sent[MAX_DESCRIPTORS] = {0};
+static unsigned long* already_sent = NULL;
+
+
+void InitializeAlreadySent(SocketEngine* SE)
+{
+       already_sent = new unsigned long[SE->GetMaxFds()];
+       memset(already_sent, 0, sizeof(already_sent));
+}
 
 /* XXX: Used for speeding up WriteCommon operations */
-unsigned long uniq_id = 0;
+unsigned long uniq_id = 1;
 
 std::string User::ProcessNoticeMasks(const char *sm)
 {
@@ -91,7 +98,7 @@ void User::StartDNSLookup()
        try
        {
                bool cached;
-               const char* sip = this->GetIPString();
+               const char* sip = this->GetIPString(false);
 
                /* Special case for 4in6 (Have i mentioned i HATE 4in6?) */
                if (!strncmp(sip, "0::ffff:", 8))
@@ -193,6 +200,7 @@ User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance
        Visibility = NULL;
        ip = NULL;
        MyClass = NULL;
+       io = NULL;
        AllowedUserModes = NULL;
        AllowedChanModes = NULL;
        AllowedOperCommands = NULL;
@@ -223,7 +231,7 @@ User::~User()
        if (this->MyClass)
        {
                this->MyClass->RefCount--;
-               ServerInstance->Logs->Log("USERS", DEBUG, "User destructor -- connect refcount now: %u", this->MyClass->RefCount);
+               ServerInstance->Logs->Log("USERS", DEBUG, "User destructor -- connect refcount now: %lu", this->MyClass->RefCount);
        }
        if (this->AllowedOperCommands)
        {
@@ -307,8 +315,11 @@ char* User::MakeHostIP()
 
 void User::CloseSocket()
 {
-       ServerInstance->SE->Shutdown(this, 2);
-       ServerInstance->SE->Close(this);
+       if (this->fd > -1)
+       {
+               ServerInstance->SE->Shutdown(this, 2);
+               ServerInstance->SE->Close(this);
+       }
 }
 
 char* User::GetFullHost()
@@ -519,7 +530,7 @@ bool User::AddBuffer(std::string a)
                if (this->MyClass && (recvq.length() > this->MyClass->GetRecvqMax()))
                {
                        this->SetWriteError("RecvQ exceeded");
-                       ServerInstance->SNO->WriteToSnoMask('A', "User %s RecvQ of %d exceeds connect class maximum of %d",this->nick,recvq.length(),this->MyClass->GetRecvqMax());
+                       ServerInstance->SNO->WriteToSnoMask('A', "User %s RecvQ of %lu exceeds connect class maximum of %lu",this->nick,(unsigned long int)recvq.length(),this->MyClass->GetRecvqMax());
                        return false;
                }
 
@@ -596,7 +607,7 @@ void User::AddWriteBuf(const std::string &data)
                 * to repeatedly add the text to the sendq!
                 */
                this->SetWriteError("SendQ exceeded");
-               ServerInstance->SNO->WriteToSnoMask('A', "User %s SendQ of %d exceeds connect class maximum of %d",this->nick,sendq.length() + data.length(),this->MyClass->GetSendqMax());
+               ServerInstance->SNO->WriteToSnoMask('A', "User %s SendQ of %lu exceeds connect class maximum of %lu",this->nick,(unsigned long int)sendq.length() + data.length(),this->MyClass->GetSendqMax());
                return;
        }
 
@@ -806,21 +817,6 @@ void User::UnOper()
        }
 }
 
-void User::QuitUser(InspIRCd* Instance, User *user, const std::string &quitreason, const char* operreason)
-{
-       Instance->Logs->Log("USERS", DEBUG,"QuitUser: %s '%s'", user->nick, quitreason.c_str());
-       user->Write("ERROR :Closing link (%s@%s) [%s]", user->ident, user->host, *operreason ? operreason : quitreason.c_str());
-       user->quietquit = false;
-       user->quitmsg = quitreason;
-
-       if (!*operreason)
-               user->operquitmsg = quitreason;
-       else
-               user->operquitmsg = operreason;
-
-       Instance->GlobalCulls.AddItem(user);
-}
-
 /* adds or updates an entry in the whowas list */
 void User::AddToWhoWas()
 {
@@ -842,18 +838,18 @@ void User::CheckClass()
 
        if ((!a) || (a->GetType() == CC_DENY))
        {
-               User::QuitUser(ServerInstance, this, "Unauthorised connection");
+               ServerInstance->Users->QuitUser(this, "Unauthorised connection");
                return;
        }
        else if ((a->GetMaxLocal()) && (ServerInstance->Users->LocalCloneCount(this) > a->GetMaxLocal()))
        {
-               User::QuitUser(ServerInstance, this, "No more connections allowed from your host via this connect class (local)");
+               ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (local)");
                ServerInstance->SNO->WriteToSnoMask('A', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString());
                return;
        }
        else if ((a->GetMaxGlobal()) && (ServerInstance->Users->GlobalCloneCount(this) > a->GetMaxGlobal()))
        {
-               User::QuitUser(ServerInstance, this, "No more connections allowed from your host via this connect class (global)");
+               ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (global)");
                ServerInstance->SNO->WriteToSnoMask('A', "WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString());
                return;
        }
@@ -863,6 +859,25 @@ void User::CheckClass()
        this->MaxChans = a->GetMaxChans();
 }
 
+void User::CheckLines()
+{
+       const char* check[] = { "G" , "K", NULL };
+
+       if (!this->exempt)
+       {
+               for (int n = 0; check[n]; ++n)
+               {
+                       XLine *r = ServerInstance->XLines->MatchesLine(check[n], this);
+
+                       if (r)
+                       {
+                               r->Apply(this);
+                               return;
+                       }
+               }
+       }
+}
+
 void User::FullConnect()
 {
        ServerInstance->stats->statsConnects++;
@@ -881,37 +896,19 @@ void User::FullConnect()
         */
        if (this->MyClass && !this->MyClass->GetPass().empty() && !this->haspassed)
        {
-               User::QuitUser(ServerInstance, this, "Invalid password");
+               ServerInstance->Users->QuitUser(this, "Invalid password");
                return;
        }
 
-       if (!this->exempt)
-       {
-               GLine *r = (GLine *)ServerInstance->XLines->MatchesLine("G", this);
-
-               if (r)
-               {
-                       r->Apply(this);
-                       return;
-               }
-
-               KLine *n = (KLine *)ServerInstance->XLines->MatchesLine("K", this);
-
-               if (n)
-               {
-                       n->Apply(this);
-                       return;
-               }
-       }
+       CheckLines();
 
        this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network);
        this->WriteNumeric(001, "%s :Welcome to the %s IRC Network %s!%s@%s",this->nick, ServerInstance->Config->Network, this->nick, this->ident, this->host);
-       this->WriteNumeric(002, "%s :Your host is %s, running version %s",this->nick,ServerInstance->Config->ServerName,VERSION);
+       this->WriteNumeric(002, "%s :Your host is %s, running version InspIRCd-1.2",this->nick,ServerInstance->Config->ServerName);
        this->WriteNumeric(003, "%s :This server was created %s %s", this->nick, __TIME__, __DATE__);
-       this->WriteNumeric(004, "%s %s %s %s %s %s", this->nick, ServerInstance->Config->ServerName, VERSION, ServerInstance->Modes->UserModeList().c_str(), ServerInstance->Modes->ChannelModeList().c_str(), ServerInstance->Modes->ParaModeList().c_str());
+       this->WriteNumeric(004, "%s %s InspIRCd-1.2 %s %s %s", this->nick, ServerInstance->Config->ServerName, ServerInstance->Modes->UserModeList().c_str(), ServerInstance->Modes->ChannelModeList().c_str(), ServerInstance->Modes->ParaModeList().c_str());
 
        ServerInstance->Config->Send005(this);
-
        this->WriteNumeric(42, "%s %s :your unique ID", this->nick, this->uuid);
 
 
@@ -979,46 +976,29 @@ void User::InvalidateCache()
 
 bool User::ForceNickChange(const char* newnick)
 {
-       /*
-        * XXX this makes no sense..
-        * why do we do nothing for change on users not REG_ALL?
-        * why do we trigger events twice for everyone previously (and just them now)
-        * i think the first if () needs removing totally, or? -- w00t
-        */
-       if (this->registered != REG_ALL)
-       {
-               int MOD_RESULT = 0;
-
-               this->InvalidateCache();
+       int MOD_RESULT = 0;
 
-               FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(this, newnick));
+       this->InvalidateCache();
 
-               if (MOD_RESULT)
-               {
-                       ServerInstance->stats->statsCollisions++;
-                       return false;
-               }
+       FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(this, newnick));
 
-               if (ServerInstance->XLines->MatchesLine("Q",newnick))
-               {
-                       ServerInstance->stats->statsCollisions++;
-                       return false;
-               }
+       if (MOD_RESULT)
+       {
+               ServerInstance->stats->statsCollisions++;
+               return false;
        }
-       else
+
+       std::deque<classbase*> dummy;
+       Command* nickhandler = ServerInstance->Parser->GetHandler("NICK");
+       if (nickhandler) // wtfbbq, when would this not be here
        {
-               std::deque<classbase*> dummy;
-               Command* nickhandler = ServerInstance->Parser->GetHandler("NICK");
-               if (nickhandler) // wtfbbq, when would this not be here
-               {
-                       nickhandler->HandleInternal(1, dummy);
-                       bool result = (ServerInstance->Parser->CallHandler("NICK", &newnick, 1, this) == CMD_SUCCESS);
-                       nickhandler->HandleInternal(0, dummy);
-                       return result;
-               }
+               nickhandler->HandleInternal(1, dummy);
+               bool result = (ServerInstance->Parser->CallHandler("NICK", &newnick, 1, this) == CMD_SUCCESS);
+               nickhandler->HandleInternal(0, dummy);
+               return result;
        }
 
-       // Unreachable.
+       // Unreachable, we hope
        return false;
 }
 
@@ -1094,7 +1074,7 @@ int User::GetProtocolFamily()
  * XXX the duplication here is horrid..
  * do we really need two methods doing essentially the same thing?
  */
-const char* User::GetIPString()
+const char* User::GetIPString(bool translate4in6)
 {
        static char buf[1024];
 
@@ -1118,6 +1098,12 @@ const char* User::GetIPString()
                        {
                                strlcpy(&temp[1], buf, sizeof(temp) - 1);
                                *temp = '0';
+                               if (translate4in6 && !strncmp(temp, "0::ffff:", 8))
+                               {
+                                       this->cachedip = temp + 8;
+                                       return temp + 8;
+                               }
+
                                this->cachedip = temp;
                                return temp;
                        }
@@ -1165,14 +1151,14 @@ void User::Write(std::string text)
                return;
        }
 
-       if (ServerInstance->Config->GetIOHook(this->GetPort()))
+       if (this->io)
        {
                /* XXX: The lack of buffering here is NOT a bug, modules implementing this interface have to
                 * implement their own buffering mechanisms
                 */
                try
                {
-                       ServerInstance->Config->GetIOHook(this->GetPort())->OnRawSocketWrite(this->fd, text.data(), text.length());
+                       this->io->OnRawSocketWrite(this->fd, text.data(), text.length());
                }
                catch (CoreException& modexcept)
                {
@@ -1321,6 +1307,9 @@ void User::WriteCommon(const std::string &text)
 
        uniq_id++;
 
+       if (!already_sent)
+               InitializeAlreadySent(ServerInstance->SE);
+
        /* We dont want to be doing this n times, just once */
        snprintf(tb,MAXBUF,":%s %s",this->GetFullHost(),text.c_str());
        std::string out = tb;
@@ -1375,6 +1364,10 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op
                return;
 
        uniq_id++;
+
+       if (!already_sent)
+               InitializeAlreadySent(ServerInstance->SE);
+
        snprintf(tb1,MAXBUF,":%s QUIT :%s",this->GetFullHost(),normal_text.c_str());
        snprintf(tb2,MAXBUF,":%s QUIT :%s",this->GetFullHost(),oper_text.c_str());
        std::string out1 = tb1;
@@ -1406,6 +1399,10 @@ void User::WriteCommonExcept(const std::string &text)
                return;
 
        uniq_id++;
+
+       if (!already_sent)
+               InitializeAlreadySent(ServerInstance->SE);
+
        snprintf(tb1,MAXBUF,":%s %s",this->GetFullHost(),text.c_str());
        out1 = tb1;
 
@@ -1429,7 +1426,7 @@ void User::WriteCommonExcept(const std::string &text)
 
 void User::WriteWallOps(const std::string &text)
 {
-       if (!IS_OPER(this) && IS_LOCAL(this))
+       if (!IS_LOCAL(this))
                return;
 
        std::string wallop("WALLOPS :");
@@ -1445,6 +1442,9 @@ void User::WriteWallOps(const std::string &text)
 
 void User::WriteWallOps(const char* text, ...)
 {
+       if (!IS_LOCAL(this))
+               return;
+
        char textbuffer[MAXBUF];
        va_list argsPtr;
 
@@ -1707,7 +1707,7 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
                /* deny change if change will take class over the limit */
                if (found->limit && (found->RefCount + 1 >= found->limit))
                {
-                       ServerInstance->Logs->Log("USERS", DEBUG, "OOPS: Connect class limit (%u) hit, denying", found->limit);
+                       ServerInstance->Logs->Log("USERS", DEBUG, "OOPS: Connect class limit (%lu) hit, denying", found->limit);
                        return this->MyClass;
                }
 
@@ -1717,12 +1717,12 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
                        if (found == this->MyClass) // no point changing this shit :P
                                return this->MyClass;
                        this->MyClass->RefCount--;
-                       ServerInstance->Logs->Log("USERS", DEBUG, "Untying user from connect class -- refcount: %u", this->MyClass->RefCount);
+                       ServerInstance->Logs->Log("USERS", DEBUG, "Untying user from connect class -- refcount: %lu", this->MyClass->RefCount);
                }
 
                this->MyClass = found;
                this->MyClass->RefCount++;
-               ServerInstance->Logs->Log("USERS", DEBUG, "User tied to new class -- connect refcount now: %u", this->MyClass->RefCount);
+               ServerInstance->Logs->Log("USERS", DEBUG, "User tied to new class -- connect refcount now: %lu", this->MyClass->RefCount);
        }
 
        return this->MyClass;
@@ -1841,7 +1841,7 @@ void User::HandleEvent(EventType et, int errornum)
        {
                if (!WriteError.empty())
                {
-                       User::QuitUser(ServerInstance, this, GetWriteError());
+                       ServerInstance->Users->QuitUser(this, GetWriteError());
                }
        }
 }