]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/pingtimer.cpp
Fix the cloaking module on C++98 compilers.
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / pingtimer.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2019 Sadie Powell <sadie@witchery.services>
5  *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "inspircd.h"
22
23 #include "pingtimer.h"
24 #include "treeserver.h"
25 #include "commandbuilder.h"
26
27 PingTimer::PingTimer(TreeServer* ts)
28         : Timer(Utils->PingFreq)
29         , server(ts)
30         , state(PS_SENDPING)
31 {
32 }
33
34 PingTimer::State PingTimer::TickInternal()
35 {
36         // Timer expired, take next action based on what happened last time
37         if (state == PS_SENDPING)
38         {
39                 // Last ping was answered, send next ping
40                 server->GetSocket()->WriteLine(CmdBuilder("PING").push(server->GetId()));
41                 LastPingMsec = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
42                 // Warn next unless warnings are disabled. If they are, jump straight to timeout.
43                 if (Utils->PingWarnTime)
44                         return PS_WARN;
45                 else
46                         return PS_TIMEOUT;
47         }
48         else if (state == PS_WARN)
49         {
50                 // No pong arrived in PingWarnTime seconds, send a warning to opers
51                 ServerInstance->SNO->WriteToSnoMask('l', "Server \002%s\002 has not responded to PING for %d seconds, high latency.", server->GetName().c_str(), GetInterval());
52                 return PS_TIMEOUT;
53         }
54         else // PS_TIMEOUT
55         {
56                 // They didn't answer the last ping, if they are locally connected, get rid of them
57                 if (server->IsLocal())
58                 {
59                         TreeSocket* sock = server->GetSocket();
60                         sock->SendError("Ping timeout");
61                         sock->Close();
62                 }
63
64                 // If the server is non-locally connected, don't do anything until we get a PONG.
65                 // This is to avoid pinging the server and warning opers more than once.
66                 // If they do answer eventually, we will move to the PS_SENDPING state and ping them again.
67                 return PS_IDLE;
68         }
69 }
70
71 void PingTimer::SetState(State newstate)
72 {
73         state = newstate;
74
75         // Set when should the next Tick() happen based on the state
76         if (state == PS_SENDPING)
77                 SetInterval(Utils->PingFreq);
78         else if (state == PS_WARN)
79                 SetInterval(Utils->PingWarnTime);
80         else if (state == PS_TIMEOUT)
81                 SetInterval(Utils->PingFreq - Utils->PingWarnTime);
82
83         // If state == PS_IDLE, do not set the timer, see above why
84 }
85
86 bool PingTimer::Tick(time_t currtime)
87 {
88         if (server->IsDead())
89                 return false;
90
91         SetState(TickInternal());
92         return false;
93 }
94
95 void PingTimer::OnPong()
96 {
97         // Calculate RTT
98         long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
99         server->rtt = ts - LastPingMsec;
100
101         // Change state to send ping next, also reschedules the timer appropriately
102         SetState(PS_SENDPING);
103 }