]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/main.cpp
Poach feature request: If a server does not respond after x seconds to a PING, send...
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / main.cpp
index 31f8a1f10afc15a670f5249083b6e97c1f464fb9..4dc6eedc0e9d3d4e4cf0cb4a3875b205db6821a7 100644 (file)
@@ -50,6 +50,9 @@ ModuleSpanningTree::ModuleSpanningTree(InspIRCd* Me)
        }
        else
                SyncTimer = NULL;
+
+       RefreshTimer = new CacheRefreshTimer(ServerInstance, Utils);
+       ServerInstance->Timers->AddTimer(RefreshTimer);
 }
 
 void ModuleSpanningTree::ShowLinks(TreeServer* Current, userrec* user, int hops)
@@ -61,7 +64,7 @@ void ModuleSpanningTree::ShowLinks(TreeServer* Current, userrec* user, int hops)
        }
        for (unsigned int q = 0; q < Current->ChildCount(); q++)
        {
-               if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName().c_str())))
+               if ((Current->GetChild(q)->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName().c_str()))))
                {
                        if (*user->oper)
                        {
@@ -74,9 +77,16 @@ void ModuleSpanningTree::ShowLinks(TreeServer* Current, userrec* user, int hops)
                }
        }
        /* Don't display the line if its a uline, hide ulines is on, and the user isnt an oper */
-       if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName().c_str())) && (!*user->oper))
+       if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName().c_str())) && (!IS_OPER(user)))
+               return;
+       /* Or if the server is hidden and they're not an oper */
+       else if ((Current->Hidden) && (!IS_OPER(user)))
                return;
-       user->WriteServ("364 %s %s %s :%d %s",user->nick,Current->GetName().c_str(),(Utils->FlatLinks && (!*user->oper)) ? ServerInstance->Config->ServerName : Parent.c_str(),(Utils->FlatLinks && (!*user->oper)) ? 0 : hops,Current->GetDesc().c_str());
+
+       user->WriteServ("364 %s %s %s :%d %s",  user->nick,Current->GetName().c_str(),
+                       (Utils->FlatLinks && (!IS_OPER(user))) ? ServerInstance->Config->ServerName : Parent.c_str(),
+                       (Utils->FlatLinks && (!IS_OPER(user))) ? 0 : hops,
+                       Current->GetDesc().c_str());
 }
 
 int ModuleSpanningTree::CountLocalServs()
@@ -131,14 +141,29 @@ void ModuleSpanningTree::HandleLusers(const char** parameters, int pcnt, userrec
                user->WriteServ("253 %s %d :unknown connections",user->nick,ServerInstance->UnregisteredUserCount());
        if (ServerInstance->ChannelCount())
                user->WriteServ("254 %s %d :channels formed",user->nick,ServerInstance->ChannelCount());
-       user->WriteServ("254 %s :I have %d clients and %d servers",user->nick,ServerInstance->LocalUserCount(),ulined_local_count ? this->CountLocalServs() - ulined_local_count : this->CountLocalServs());
+       user->WriteServ("255 %s :I have %d clients and %d servers",user->nick,ServerInstance->LocalUserCount(),ulined_local_count ? this->CountLocalServs() - ulined_local_count : this->CountLocalServs());
        user->WriteServ("265 %s :Current Local Users: %d  Max: %d",user->nick,ServerInstance->LocalUserCount(),max_local);
        user->WriteServ("266 %s :Current Global Users: %d  Max: %d",user->nick,n_users,max_global);
        return;
 }
 
+const std::string ModuleSpanningTree::MapOperInfo(TreeServer* Current)
+{
+       time_t secs_up = ServerInstance->Time() - Current->age;
+       time_t mins_up = secs_up / 60;
+       time_t hours_up = mins_up / 60;
+       time_t days_up = hours_up / 24;
+       secs_up = secs_up % 60;
+       mins_up = mins_up % 60;
+       hours_up = hours_up % 24;
+       return (" [Up: "+ (days_up ? (ConvToStr(days_up) + "d") : std::string(""))
+                       + (hours_up ? (ConvToStr(hours_up) + "h") : std::string(""))
+                       + (mins_up ? (ConvToStr(mins_up) + "m") : std::string(""))
+                       + ConvToStr(secs_up) + "s Lag: "+ConvToStr(Current->rtt)+"s]");
+}
+
 // WARNING: NOT THREAD SAFE - DONT GET ANY SMART IDEAS.
-void ModuleSpanningTree::ShowMap(TreeServer* Current, userrec* user, int depth, char matrix[128][80], float &totusers, float &totservers)
+void ModuleSpanningTree::ShowMap(TreeServer* Current, userrec* user, int depth, char matrix[128][128], float &totusers, float &totservers)
 {
        if (line < 128)
        {
@@ -158,7 +183,10 @@ void ModuleSpanningTree::ShowMap(TreeServer* Current, userrec* user, int depth,
                        spacer[5] = '\0';
                }
                float percent;
-               char text[80];
+               char text[128];
+               /* Neat and tidy default values, as we're dealing with a matrix not a simple string */
+               memset(text, 0, 128);
+
                if (ServerInstance->clientlist->size() == 0) {
                        // If there are no users, WHO THE HELL DID THE /MAP?!?!?!
                        percent = 0;
@@ -167,14 +195,15 @@ void ModuleSpanningTree::ShowMap(TreeServer* Current, userrec* user, int depth,
                {
                        percent = ((float)Current->GetUserCount() / (float)ServerInstance->clientlist->size()) * 100;
                }
-               snprintf(text, 80, "%s %s%5d [%5.2f%%]", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent);
+               const std::string operdata = IS_OPER(user) ? MapOperInfo(Current) : "";
+               snprintf(text, 126, "%s %s%5d [%5.2f%%]%s", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent, operdata.c_str());
                totusers += Current->GetUserCount();
                totservers++;
-               strlcpy(&matrix[line][depth],text,80);
+               strlcpy(&matrix[line][depth],text,126);
                line++;
                for (unsigned int q = 0; q < Current->ChildCount(); q++)
                {
-                       if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName().c_str())))
+                       if ((Current->GetChild(q)->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName().c_str()))))
                        {
                                if (*user->oper)
                                {
@@ -193,19 +222,18 @@ int ModuleSpanningTree::HandleMotd(const char** parameters, int pcnt, userrec* u
 {
        if (pcnt > 0)
        {
+               if (match(ServerInstance->Config->ServerName, parameters[0]))
+                       return 0;
+
                /* Remote MOTD, the server is within the 1st parameter */
                std::deque<std::string> params;
                params.push_back(parameters[0]);
                /* Send it out remotely, generate no reply yet */
                TreeServer* s = Utils->FindServerMask(parameters[0]);
                if (s)
-               {
                        Utils->DoOneToOne(user->nick, "MOTD", params, s->GetName());
-               }
                else
-               {
                        user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
-               }
                return 1;
        }
        return 0;
@@ -215,33 +243,51 @@ int ModuleSpanningTree::HandleAdmin(const char** parameters, int pcnt, userrec*
 {
        if (pcnt > 0)
        {
+               if (match(ServerInstance->Config->ServerName, parameters[0]))
+                       return 1;
+
                /* Remote ADMIN, the server is within the 1st parameter */
                std::deque<std::string> params;
                params.push_back(parameters[0]);
                /* Send it out remotely, generate no reply yet */
                TreeServer* s = Utils->FindServerMask(parameters[0]);
                if (s)
-               {
                        Utils->DoOneToOne(user->nick, "ADMIN", params, s->GetName());
-               }
                else
-               {
                        user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
-               }
                return 1;
        }
        return 0;
 }
 
+int ModuleSpanningTree::HandleModules(const char** parameters, int pcnt, userrec* user)
+{
+       if (match(ServerInstance->Config->ServerName, parameters[0]))
+               return 1;
+
+       std::deque<std::string> params;
+       params.push_back(parameters[0]);
+       TreeServer* s = Utils->FindServerMask(parameters[0]);
+       if (s)
+               Utils->DoOneToOne(user->nick, "MODULES", params, s->GetName());
+       else
+               user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
+       return 1;
+}
+
 int ModuleSpanningTree::HandleStats(const char** parameters, int pcnt, userrec* user)
 {
        if (pcnt > 1)
        {
+               if (match(ServerInstance->Config->ServerName, parameters[1]))
+                       return 0;
+
                /* Remote STATS, the server is within the 2nd parameter */
                std::deque<std::string> params;
                params.push_back(parameters[0]);
                params.push_back(parameters[1]);
                /* Send it out remotely, generate no reply yet */
+
                TreeServer* s = Utils->FindServerMask(parameters[1]);
                if (s)
                {
@@ -250,7 +296,7 @@ int ModuleSpanningTree::HandleStats(const char** parameters, int pcnt, userrec*
                }
                else
                {
-                       user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
+                       user->WriteServ( "402 %s %s :No such server", user->nick, parameters[1]);
                }
                return 1;
        }
@@ -272,7 +318,7 @@ void ModuleSpanningTree::HandleMap(const char** parameters, int pcnt, userrec* u
        // client does not provide for a proper terminal.
        float totusers = 0;
        float totservers = 0;
-       char matrix[128][80];
+       char matrix[128][128];
        for (unsigned int t = 0; t < 128; t++)
        {
                matrix[t][0] = '\0';
@@ -416,11 +462,14 @@ void ModuleSpanningTree::DoPingChecks(time_t curtime)
                                {
                                        sock->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" PING "+serv->GetName());
                                        serv->SetNextPingTime(curtime + 60);
+                                       serv->LastPing = curtime;
+                                       serv->Warned = false;
                                }
                                else
                                {
                                        // they didnt answer, boot them
                                        ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 pinged out",serv->GetName().c_str());
+                                       sock->SendError("Ping timeout");
                                        sock->Squit(serv,"Ping timeout");
                                        ServerInstance->SE->DelFd(sock);
                                        sock->Close();
@@ -428,6 +477,12 @@ void ModuleSpanningTree::DoPingChecks(time_t curtime)
                                        return;
                                }
                        }
+                       else if ((Utils->PingWarnTime) && (!serv->Warned) && (curtime >= serv->NextPingTime() - (60 - Utils->PingWarnTime)) && (!serv->AnsweredLastPing()))
+                       {
+                               /* The server hasnt responded, send a warning to opers */
+                               ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not responded to PING for %d seconds, high latency.", serv->GetName().c_str(), Utils->PingWarnTime);
+                               serv->Warned = true;
+                       }
                }
        }
 }
@@ -566,9 +621,13 @@ int ModuleSpanningTree::HandleConnect(const char** parameters, int pcnt, userrec
 
 void ModuleSpanningTree::BroadcastTimeSync()
 {
-       std::deque<std::string> params;
-       params.push_back(ConvToStr(ServerInstance->Time(true)));
-       Utils->DoOneToMany(Utils->TreeRoot->GetName(), "TIMESET", params);
+       if (Utils->MasterTime)
+       {
+               std::deque<std::string> params;
+               params.push_back(ConvToStr(ServerInstance->Time(false)));
+               params.push_back("FORCE");
+               Utils->DoOneToMany(Utils->TreeRoot->GetName(), "TIMESET", params);
+       }
 }
 
 int ModuleSpanningTree::OnStats(char statschar, userrec* user, string_list &results)
@@ -593,6 +652,7 @@ int ModuleSpanningTree::OnPreCommand(const std::string &command, const char** pa
        /* If the command doesnt appear to be valid, we dont want to mess with it. */
        if (!validated)
                return 0;
+
        if (command == "CONNECT")
        {
                return this->HandleConnect(parameters,pcnt,user);
@@ -645,6 +705,10 @@ int ModuleSpanningTree::OnPreCommand(const std::string &command, const char** pa
                this->HandleVersion(parameters,pcnt,user);
                return 1;
        }
+       else if ((command == "MODULES") && (pcnt > 0))
+       {
+               return this->HandleModules(parameters,pcnt,user);
+       }
        return 0;
 }
 
@@ -816,7 +880,7 @@ void ModuleSpanningTree::OnBackgroundTimer(time_t curtime)
        DoPingChecks(curtime);
 }
 
-void ModuleSpanningTree::OnUserJoin(userrec* user, chanrec* channel)
+void ModuleSpanningTree::OnUserJoin(userrec* user, chanrec* channel, bool &silent)
 {
        // Only do this for local users
        if (IS_LOCAL(user))
@@ -867,7 +931,7 @@ void ModuleSpanningTree::OnChangeName(userrec* user, const std::string &gecos)
        Utils->DoOneToMany(user->nick,"FNAME",params);
 }
 
-void ModuleSpanningTree::OnUserPart(userrec* user, chanrec* channel, const std::string &partmessage)
+void ModuleSpanningTree::OnUserPart(userrec* user, chanrec* channel, const std::string &partmessage, bool &silent)
 {
        if (IS_LOCAL(user))
        {
@@ -904,11 +968,18 @@ void ModuleSpanningTree::OnUserConnect(userrec* user)
        }
 }
 
-void ModuleSpanningTree::OnUserQuit(userrec* user, const std::string &reason)
+void ModuleSpanningTree::OnUserQuit(userrec* user, const std::string &reason, const std::string &oper_message)
 {
        if ((IS_LOCAL(user)) && (user->registered == REG_ALL))
        {
                std::deque<std::string> params;
+
+               if (oper_message != reason)
+               {
+                       params.push_back(":"+oper_message);
+                       Utils->DoOneToMany(user->nick,"OPERQUIT",params);
+               }
+               params.clear();
                params.push_back(":"+reason);
                Utils->DoOneToMany(user->nick,"QUIT",params);
        }
@@ -930,7 +1001,7 @@ void ModuleSpanningTree::OnUserPostNick(userrec* user, const std::string &oldnic
        }
 }
 
-void ModuleSpanningTree::OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason)
+void ModuleSpanningTree::OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason, bool &silent)
 {
        if ((source) && (IS_LOCAL(source)))
        {
@@ -1072,22 +1143,25 @@ void ModuleSpanningTree::OnMode(userrec* user, void* dest, int target_type, cons
 {
        if ((IS_LOCAL(user)) && (user->registered == REG_ALL))
        {
+               std::deque<std::string> params;
+               std::string command;
+
                if (target_type == TYPE_USER)
                {
                        userrec* u = (userrec*)dest;
-                       std::deque<std::string> params;
                        params.push_back(u->nick);
                        params.push_back(text);
-                       Utils->DoOneToMany(user->nick,"MODE",params);
+                       command = "MODE";
                }
                else
                {
                        chanrec* c = (chanrec*)dest;
-                       std::deque<std::string> params;
                        params.push_back(c->name);
+                       params.push_back(ConvToStr(c->age));
                        params.push_back(text);
-                       Utils->DoOneToMany(user->nick,"MODE",params);
+                       command = "FMODE";
                }
+               Utils->DoOneToMany(user->nick, command, params);
        }
 }
 
@@ -1241,6 +1315,8 @@ ModuleSpanningTree::~ModuleSpanningTree()
        if (SyncTimer)
                ServerInstance->Timers->DelTimer(SyncTimer);
 
+       ServerInstance->Timers->DelTimer(RefreshTimer);
+
        ServerInstance->DoneWithInterface("InspSocketHook");
 }