]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge branch 'master+foreachneighbor'
authorAttila Molnar <attilamolnar@hush.com>
Mon, 26 Jan 2015 14:05:22 +0000 (15:05 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Mon, 26 Jan 2015 14:05:22 +0000 (15:05 +0100)
include/ctables.h
src/command_parse.cpp
src/modules/m_spanningtree/main.cpp
src/modules/m_spanningtree/main.h
src/modules/m_spanningtree/pingtimer.cpp [new file with mode: 0644]
src/modules/m_spanningtree/pingtimer.h [new file with mode: 0644]
src/modules/m_spanningtree/pong.cpp
src/modules/m_spanningtree/treeserver.cpp
src/modules/m_spanningtree/treeserver.h

index a69f5c86f65e14c3fc18ae7abdd75b4deee4905c..abf65f56127122f2e742b76592b3b65fdd8f23fe 100644 (file)
@@ -163,36 +163,16 @@ class CoreExport CommandBase : public ServiceProvider
         * @param maxpara Maximum number of parameters this command may have - extra parameters
         * will be tossed into one last space-seperated param.
         */
-       CommandBase(Module* me, const std::string &cmd, int minpara = 0, int maxpara = 0) :
-               ServiceProvider(me, cmd, SERVICE_COMMAND), flags_needed(0), min_params(minpara), max_params(maxpara),
-               use_count(0), disabled(false), works_before_reg(false), allow_empty_last_param(true),
-               Penalty(1)
-       {
-       }
+       CommandBase(Module* me, const std::string& cmd, unsigned int minpara = 0, unsigned int maxpara = 0);
 
-       virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
-       {
-               return ROUTE_LOCALONLY;
-       }
+       virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters);
 
        /** Encode a parameter for server->server transmission.
         * Used for parameters for which the translation type is TR_CUSTOM.
         * @param parameter The parameter to encode. Can be modified in place.
         * @param index The parameter index (0 == first parameter).
         */
-       virtual void EncodeParameter(std::string& parameter, int index)
-       {
-       }
-
-       /** Decode a parameter from server->server transmission.
-        * Not currently used in this version of InspIRCd.
-        * Used for parameters for which the translation type is TR_CUSTOM.
-        * @param parameter The parameter to decode. Can be modified in place.
-        * @param index The parameter index (0 == first parameter).
-        */
-       virtual void DecodeParameter(std::string& parameter, int index)
-       {
-       }
+       virtual void EncodeParameter(std::string& parameter, int index);
 
        /** Disable or enable this command.
         * @param setting True to disable the command.
@@ -229,11 +209,7 @@ class CoreExport Command : public CommandBase
         */
        bool force_manual_route;
 
-       Command(Module* me, const std::string& cmd, unsigned int minpara = 0, unsigned int maxpara = 0)
-               : CommandBase(me, cmd, minpara, maxpara)
-               , force_manual_route(false)
-       {
-       }
+       Command(Module* me, const std::string& cmd, unsigned int minpara = 0, unsigned int maxpara = 0);
 
        /** Handle the command from a user.
         * @param parameters The parameters for the command.
index 793569d5bedc75b9d25dc84731869611cca0c548..c93dac65fd386c05bff39ae57307c87dde5117e0 100644 (file)
@@ -327,10 +327,38 @@ void CommandParser::RemoveCommand(Command* x)
                cmdlist.erase(n);
 }
 
+CommandBase::CommandBase(Module* mod, const std::string& cmd, unsigned int minpara, unsigned int maxpara)
+       : ServiceProvider(mod, cmd, SERVICE_COMMAND)
+       , flags_needed(0)
+       , min_params(minpara)
+       , max_params(maxpara)
+       , use_count(0)
+       , disabled(false)
+       , works_before_reg(false)
+       , allow_empty_last_param(true)
+       , Penalty(1)
+{
+}
+
 CommandBase::~CommandBase()
 {
 }
 
+void CommandBase::EncodeParameter(std::string& parameter, int index)
+{
+}
+
+RouteDescriptor CommandBase::GetRouting(User* user, const std::vector<std::string>& parameters)
+{
+       return ROUTE_LOCALONLY;
+}
+
+Command::Command(Module* mod, const std::string& cmd, unsigned int minpara, unsigned int maxpara)
+       : CommandBase(mod, cmd, minpara, maxpara)
+       , force_manual_route(false)
+{
+}
+
 Command::~Command()
 {
        ServerInstance->Parser.RemoveCommand(this);
index c21064683057dff28d8c9f3767616e034d55b37d..31d8227894205f00edd71f48fcad0ee23b4e623c 100644 (file)
@@ -153,64 +153,6 @@ std::string ModuleSpanningTree::TimeToStr(time_t secs)
                        + ConvToStr(secs) + "s");
 }
 
-void ModuleSpanningTree::DoPingChecks(time_t curtime)
-{
-       /*
-        * Cancel remote burst mode on any servers which still have it enabled due to latency/lack of data.
-        * This prevents lost REMOTECONNECT notices
-        */
-       long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
-
-restart:
-       for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++)
-       {
-               TreeServer *s = i->second;
-
-               // Skip myself
-               if (s->IsRoot())
-                       continue;
-
-               // Do not ping servers that are not fully connected yet!
-               // Servers which are connected to us have IsLocal() == true and if they're fully connected
-               // then Socket->LinkState == CONNECTED. Servers that are linked to another server are always fully connected.
-               if (s->IsLocal() && s->GetSocket()->GetLinkState() != CONNECTED)
-                       continue;
-
-               // Now do PING checks on all servers
-               // Only ping if this server needs one
-               if (curtime >= s->NextPingTime())
-               {
-                       // And if they answered the last
-                       if (s->AnsweredLastPing())
-                       {
-                               // They did, send a ping to them
-                               s->SetNextPingTime(curtime + Utils->PingFreq);
-                               s->GetSocket()->WriteLine(CmdBuilder("PING").push(s->GetID()));
-                               s->LastPingMsec = ts;
-                       }
-                       else
-                       {
-                               // They didn't answer the last ping, if they are locally connected, get rid of them.
-                               if (s->IsLocal())
-                               {
-                                       TreeSocket* sock = s->GetSocket();
-                                       sock->SendError("Ping timeout");
-                                       sock->Close();
-                                       goto restart;
-                               }
-                       }
-               }
-
-               // If warn on ping enabled and not warned and the difference is sufficient and they didn't answer the last ping...
-               if ((Utils->PingWarnTime) && (!s->Warned) && (curtime >= s->NextPingTime() - (Utils->PingFreq - Utils->PingWarnTime)) && (!s->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.", s->GetName().c_str(), Utils->PingWarnTime);
-                       s->Warned = true;
-               }
-       }
-}
-
 void ModuleSpanningTree::ConnectServer(Autoconnect* a, bool on_timer)
 {
        if (!a)
@@ -471,7 +413,6 @@ void ModuleSpanningTree::OnUserMessage(User* user, void* dest, int target_type,
 void ModuleSpanningTree::OnBackgroundTimer(time_t curtime)
 {
        AutoConnectServers(curtime);
-       DoPingChecks(curtime);
        DoConnectTimeout(curtime);
 }
 
index c81eb2d0bc023a9a97411c671b769ea78ee376c4..13c743f731387cd4ecdabd8851cd981c85120643 100644 (file)
@@ -103,10 +103,6 @@ class ModuleSpanningTree : public Module
         */
        ModResult HandleRemoteWhois(const std::vector<std::string>& parameters, User* user);
 
-       /** Ping all local servers
-        */
-       void DoPingChecks(time_t curtime);
-
        /** Connect a server locally
         */
        void ConnectServer(Link* x, Autoconnect* y = NULL);
diff --git a/src/modules/m_spanningtree/pingtimer.cpp b/src/modules/m_spanningtree/pingtimer.cpp
new file mode 100644 (file)
index 0000000..1c96259
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+
+#include "pingtimer.h"
+#include "treeserver.h"
+#include "commandbuilder.h"
+
+PingTimer::PingTimer(TreeServer* ts)
+       : Timer(Utils->PingFreq)
+       , server(ts)
+       , state(PS_SENDPING)
+{
+}
+
+PingTimer::State PingTimer::TickInternal()
+{
+       // Timer expired, take next action based on what happened last time
+       if (state == PS_SENDPING)
+       {
+               // Last ping was answered, send next ping
+               server->GetSocket()->WriteLine(CmdBuilder("PING").push(server->GetID()));
+               LastPingMsec = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
+               // Warn next unless warnings are disabled. If they are, jump straight to timeout.
+               if (Utils->PingWarnTime)
+                       return PS_WARN;
+               else
+                       return PS_TIMEOUT;
+       }
+       else if (state == PS_WARN)
+       {
+               // No pong arrived in PingWarnTime seconds, send a warning to opers
+               ServerInstance->SNO->WriteToSnoMask('l', "Server \002%s\002 has not responded to PING for %d seconds, high latency.", server->GetName().c_str(), GetInterval());
+               return PS_TIMEOUT;
+       }
+       else // PS_TIMEOUT
+       {
+               // They didn't answer the last ping, if they are locally connected, get rid of them
+               if (server->IsLocal())
+               {
+                       TreeSocket* sock = server->GetSocket();
+                       sock->SendError("Ping timeout");
+                       sock->Close();
+               }
+
+               // If the server is non-locally connected, don't do anything until we get a PONG.
+               // This is to avoid pinging the server and warning opers more than once.
+               // If they do answer eventually, we will move to the PS_SENDPING state and ping them again.
+               return PS_IDLE;
+       }
+}
+
+void PingTimer::SetState(State newstate)
+{
+       state = newstate;
+
+       // Set when should the next Tick() happen based on the state
+       if (state == PS_SENDPING)
+               SetInterval(Utils->PingFreq);
+       else if (state == PS_WARN)
+               SetInterval(Utils->PingWarnTime);
+       else if (state == PS_TIMEOUT)
+               SetInterval(Utils->PingFreq - Utils->PingWarnTime);
+
+       // If state == PS_IDLE, do not set the timer, see above why
+}
+
+bool PingTimer::Tick(time_t currtime)
+{
+       if (server->IsDead())
+               return false;
+
+       SetState(TickInternal());
+       return false;
+}
+
+void PingTimer::OnPong()
+{
+       // Calculate RTT
+       long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
+       server->rtt = ts - LastPingMsec;
+
+       // Change state to send ping next, also reschedules the timer appropriately
+       SetState(PS_SENDPING);
+}
diff --git a/src/modules/m_spanningtree/pingtimer.h b/src/modules/m_spanningtree/pingtimer.h
new file mode 100644 (file)
index 0000000..7535586
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+class TreeServer;
+
+/** Handles PINGing servers and killing them on timeout
+ */
+class PingTimer : public Timer
+{
+       enum State
+       {
+               /** Send PING next */
+               PS_SENDPING,
+               /** Warn opers next */
+               PS_WARN,
+               /** Kill the server next due to ping timeout */
+               PS_TIMEOUT,
+               /** Do nothing */
+               PS_IDLE
+       };
+
+       /** Server the timer is interacting with
+        */
+       TreeServer* const server;
+
+       /** What to do when the timer ticks next
+        */
+       State state;
+
+       /** Last ping time in milliseconds, used to calculate round trip time
+        */
+       unsigned long LastPingMsec;
+
+       /** Update internal state and reschedule timer according to the new state
+        * @param newstate State to change to
+        */
+       void SetState(State newstate);
+
+       /** Process timer tick event
+        * @return State to change to
+        */
+       State TickInternal();
+
+       /** Called by the TimerManager when the timer expires
+        * @param currtime Time now
+        * @return Always false, we reschedule ourselves instead
+        */
+       bool Tick(time_t currtime) CXX11_OVERRIDE;
+
+ public:
+       /** Construct the timer. This doesn't schedule the timer.
+        * @param server TreeServer to interact with
+        */
+       PingTimer(TreeServer* server);
+
+       /** Register a PONG from the server
+        */
+       void OnPong();
+};
index a7dc64f83b4c2d011ede3a12e0d30a380aed7625..5d97f2af2e8508bb8609c2d1ffdb16288ff256b1 100644 (file)
@@ -35,9 +35,7 @@ CmdResult CommandPong::HandleServer(TreeServer* server, std::vector<std::string>
        if (params[0] == ServerInstance->Config->GetSID())
        {
                // PONG for us
-               long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
-               server->rtt = ts - server->LastPingMsec;
-               server->SetPingFlag();
+               server->OnPong();
        }
        return CMD_SUCCESS;
 }
index 534315ff71be9566b3215183cf839409ecf744e2..e004f897ec55bc831d47a992b8a4fdea4cd28871 100644 (file)
@@ -38,8 +38,9 @@ TreeServer::TreeServer()
        , VersionString(ServerInstance->GetVersionString())
        , fullversion(ServerInstance->GetVersionString(true))
        , Socket(NULL), sid(ServerInstance->Config->GetSID()), behind_bursting(0), isdead(false)
+       , pingtimer(this)
        , ServerUser(ServerInstance->FakeClient)
-       , age(ServerInstance->Time()), Warned(false), UserCount(ServerInstance->Users.GetLocalUsers().size())
+       , age(ServerInstance->Time()), UserCount(ServerInstance->Users.GetLocalUsers().size())
        , OperCount(0), rtt(0), StartBurst(0), Hidden(false)
 {
        AddHashEntry();
@@ -52,13 +53,14 @@ TreeServer::TreeServer()
 TreeServer::TreeServer(const std::string& Name, const std::string& Desc, const std::string& id, TreeServer* Above, TreeSocket* Sock, bool Hide)
        : Server(Name, Desc)
        , Parent(Above), Socket(Sock), sid(id), behind_bursting(Parent->behind_bursting), isdead(false)
+       , pingtimer(this)
        , ServerUser(new FakeUser(id, this))
-       , age(ServerInstance->Time()), Warned(false), UserCount(0), OperCount(0), rtt(0), StartBurst(0), Hidden(Hide)
+       , age(ServerInstance->Time()), UserCount(0), OperCount(0), rtt(0), StartBurst(0), Hidden(Hide)
 {
        ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "New server %s behind_bursting %u", GetName().c_str(), behind_bursting);
        CheckULine();
-       SetNextPingTime(ServerInstance->Time() + Utils->PingFreq);
-       SetPingFlag();
+
+       ServerInstance->Timers.AddTimer(&pingtimer);
 
        /* find the 'route' for this server (e.g. the one directly connected
         * to the local server, which we can use to reach it)
@@ -135,11 +137,6 @@ void TreeServer::FinishBurstInternal()
                behind_bursting--;
        ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "FinishBurstInternal() %s behind_bursting %u", GetName().c_str(), behind_bursting);
 
-       if (!IsBehindBursting())
-       {
-               SetNextPingTime(ServerInstance->Time() + Utils->PingFreq);
-               SetPingFlag();
-       }
        for (ChildServers::const_iterator i = Children.begin(); i != Children.end(); ++i)
        {
                TreeServer* child = *i;
@@ -261,27 +258,6 @@ void TreeServer::AddHashEntry()
        Utils->sidlist[sid] = this;
 }
 
-void TreeServer::SetNextPingTime(time_t t)
-{
-       this->NextPing = t;
-       LastPingWasGood = false;
-}
-
-time_t TreeServer::NextPingTime()
-{
-       return NextPing;
-}
-
-bool TreeServer::AnsweredLastPing()
-{
-       return LastPingWasGood;
-}
-
-void TreeServer::SetPingFlag()
-{
-       LastPingWasGood = true;
-}
-
 CullResult TreeServer::cull()
 {
        // Recursively cull all servers that are under us in the tree
index 4465de15e4ea439563a86e0f4b3eae6eed2b4aab..1a0203ba09384b9ba989de4818141cb5ba760be7 100644 (file)
@@ -22,6 +22,7 @@
 #pragma once
 
 #include "treesocket.h"
+#include "pingtimer.h"
 
 /** Each server in the tree is represented by one class of
  * type TreeServer. A locally connected TreeServer can
@@ -49,8 +50,6 @@ class TreeServer : public Server
        std::string fullversion;
 
        TreeSocket* Socket;                     /* Socket used to communicate with this server */
-       time_t NextPing;                        /* After this time, the server should be PINGed*/
-       bool LastPingWasGood;                   /* True if the server responded to the last PING with a PONG */
        std::string sid;                        /* Server ID */
 
        /** Counter counting how many servers are bursting in front of this server, including
@@ -64,6 +63,10 @@ class TreeServer : public Server
         */
        bool isdead;
 
+       /** Timer handling PINGing the server and killing it on timeout
+        */
+       PingTimer pingtimer;
+
        /** This method is used to add this TreeServer to the
         * hash maps. It is only called by the constructors.
         */
@@ -82,8 +85,6 @@ class TreeServer : public Server
        FakeUser* const ServerUser;             /* User representing this server */
        const time_t age;
 
-       bool Warned;                            /* True if we've warned opers about high latency on this server */
-
        unsigned int UserCount;                 /* How many users are on this server? [note: doesn't care about +i] */
        unsigned int OperCount;                 /* How many opers are on this server? */
 
@@ -143,18 +144,6 @@ class TreeServer : public Server
         */
        const std::string& GetFullVersion() const { return fullversion; }
 
-       /** Set time we are next due to ping this server
-        */
-       void SetNextPingTime(time_t t);
-
-       /** Get the time we are next due to ping this server
-        */
-       time_t NextPingTime();
-
-       /** Last ping time in milliseconds, used to calculate round trip time
-        */
-       unsigned long LastPingMsec;
-
        /** Round trip time of last ping
         */
        unsigned long rtt;
@@ -167,14 +156,6 @@ class TreeServer : public Server
         */
        bool Hidden;
 
-       /** True if the server answered their last ping
-        */
-       bool AnsweredLastPing();
-
-       /** Set the server as responding to its last ping
-        */
-       void SetPingFlag();
-
        /** Get the TreeSocket pointer for local servers.
         * For remote servers, this returns NULL.
         */
@@ -234,6 +215,10 @@ class TreeServer : public Server
         */
        void BeginBurst(unsigned long startms = 0);
 
+       /** Register a PONG from the server
+        */
+       void OnPong() { pingtimer.OnPong(); }
+
        CullResult cull();
 
        /** Destructor, deletes ServerUser unless IsRoot()