]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/treeserver.cpp
Add support for <link:hidden> fixes feature request documented in bug #247 reported...
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / treeserver.cpp
1 #include "configreader.h"
2 #include "users.h"
3 #include "channels.h"
4 #include "modules.h"
5 #include "commands/cmd_whois.h"
6 #include "commands/cmd_stats.h"
7 #include "socket.h"
8 #include "inspircd.h"
9 #include "wildcard.h"
10 #include "xline.h"
11 #include "transport.h"
12
13 #include "m_spanningtree/utils.h"
14 #include "m_spanningtree/treeserver.h"
15
16 /* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h */
17
18 TreeServer::TreeServer(SpanningTreeUtilities* Util, InspIRCd* Instance) : ServerInstance(Instance), Utils(Util)
19 {
20         Parent = NULL;
21         ServerName = "";
22         ServerDesc = "";
23         VersionString = "";
24         UserCount = OperCount = 0;
25         rtt = LastPing = 0;
26         Hidden = false;
27         VersionString = ServerInstance->GetVersionString();
28 }
29
30 /** We use this constructor only to create the 'root' item, Utils->TreeRoot, which
31  * represents our own server. Therefore, it has no route, no parent, and
32  * no socket associated with it. Its version string is our own local version.
33  */
34 TreeServer::TreeServer(SpanningTreeUtilities* Util, InspIRCd* Instance, std::string Name, std::string Desc) : ServerInstance(Instance), ServerName(Name.c_str()), ServerDesc(Desc), Utils(Util)
35 {
36         Parent = NULL;
37         VersionString = "";
38         UserCount = ServerInstance->UserCount();
39         OperCount = ServerInstance->OperCount();
40         VersionString = ServerInstance->GetVersionString();
41         Route = NULL;
42         Socket = NULL; /* Fix by brain */
43         rtt = LastPing = 0;
44         Hidden = false;
45         AddHashEntry();
46 }
47
48 /** When we create a new server, we call this constructor to initialize it.
49  * This constructor initializes the server's Route and Parent, and sets up
50  * its ping counters so that it will be pinged one minute from now.
51  */
52 TreeServer::TreeServer(SpanningTreeUtilities* Util, InspIRCd* Instance, std::string Name, std::string Desc, TreeServer* Above, TreeSocket* Sock, bool Hide)
53         : ServerInstance(Instance), Parent(Above), ServerName(Name.c_str()), ServerDesc(Desc), Socket(Sock), Utils(Util), Hidden(Hide)
54 {
55         VersionString = "";
56         UserCount = OperCount = 0;
57         this->SetNextPingTime(time(NULL) + 60);
58         this->SetPingFlag();
59         rtt = LastPing = 0;
60         /* find the 'route' for this server (e.g. the one directly connected
61          * to the local server, which we can use to reach it)
62          *
63          * In the following example, consider we have just added a TreeServer
64          * class for server G on our network, of which we are server A.
65          * To route traffic to G (marked with a *) we must send the data to
66          * B (marked with a +) so this algorithm initializes the 'Route'
67          * value to point at whichever server traffic must be routed through
68          * to get here. If we were to try this algorithm with server B,
69          * the Route pointer would point at its own object ('this').
70          *
71          *            A
72          *           / \
73          *        + B   C
74          *         / \   \
75          *        D   E   F
76          *       /         \
77          *    * G           H
78          *
79          * We only run this algorithm when a server is created, as
80          * the routes remain constant while ever the server exists, and
81          * do not need to be re-calculated.
82          */
83
84         Route = Above;
85         if (Route == Utils->TreeRoot)
86         {
87                 Route = this;
88         }
89         else
90         {
91                 while (this->Route->GetParent() != Utils->TreeRoot)
92                 {
93                         this->Route = Route->GetParent();
94                 }
95         }
96
97         /* Because recursive code is slow and takes a lot of resources,
98          * we store two representations of the server tree. The first
99          * is a recursive structure where each server references its
100          * children and its parent, which is used for netbursts and
101          * netsplits to dump the whole dataset to the other server,
102          * and the second is used for very fast lookups when routing
103          * messages and is instead a hash_map, where each item can
104          * be referenced by its server name. The AddHashEntry()
105          * call below automatically inserts each TreeServer class
106          * into the hash_map as it is created. There is a similar
107          * maintainance call in the destructor to tidy up deleted
108          * servers.
109          */
110
111         this->AddHashEntry();
112 }
113
114 int TreeServer::QuitUsers(const std::string &reason)
115 {
116         const char* reason_s = reason.c_str();
117         std::vector<userrec*> time_to_die;
118         for (user_hash::iterator n = ServerInstance->clientlist->begin(); n != ServerInstance->clientlist->end(); n++)
119         {
120                 if (!strcmp(n->second->server, this->ServerName.c_str()))
121                 {
122                         time_to_die.push_back(n->second);
123                 }
124         }
125         for (std::vector<userrec*>::iterator n = time_to_die.begin(); n != time_to_die.end(); n++)
126         {
127                 userrec* a = (userrec*)*n;
128                 if (!IS_LOCAL(a))
129                 {
130                         if (ServerInstance->Config->HideSplits)
131                                 userrec::QuitUser(ServerInstance, a, "*.net *.split", reason_s);
132                         else
133                                 userrec::QuitUser(ServerInstance, a, reason_s);
134                 }
135         }
136         return time_to_die.size();
137 }
138
139 /** This method is used to add the structure to the
140  * hash_map for linear searches. It is only called
141  * by the constructors.
142  */
143 void TreeServer::AddHashEntry()
144 {
145         server_hash::iterator iter = Utils->serverlist.find(this->ServerName.c_str());
146         if (iter == Utils->serverlist.end())
147                 Utils->serverlist[this->ServerName.c_str()] = this;
148 }
149
150 /** This method removes the reference to this object
151  * from the hash_map which is used for linear searches.
152  * It is only called by the default destructor.
153  */
154 void TreeServer::DelHashEntry()
155 {
156         server_hash::iterator iter = Utils->serverlist.find(this->ServerName.c_str());
157         if (iter != Utils->serverlist.end())
158                 Utils->serverlist.erase(iter);
159 }
160
161 /** These accessors etc should be pretty self-
162  * explanitory.
163  */
164 TreeServer* TreeServer::GetRoute()
165 {
166         return Route;
167 }
168
169 std::string TreeServer::GetName()
170 {
171         return ServerName.c_str();
172 }
173
174 std::string TreeServer::GetDesc()
175 {
176         return ServerDesc;
177 }
178
179 std::string TreeServer::GetVersion()
180 {
181         return VersionString;
182 }
183
184 void TreeServer::SetNextPingTime(time_t t)
185 {
186         this->NextPing = t;
187         LastPingWasGood = false;
188 }
189
190 time_t TreeServer::NextPingTime()
191 {
192         return NextPing;
193 }
194
195 bool TreeServer::AnsweredLastPing()
196 {
197         return LastPingWasGood;
198 }
199
200 void TreeServer::SetPingFlag()
201 {
202         LastPingWasGood = true;
203 }
204
205 int TreeServer::GetUserCount()
206 {
207         return UserCount;
208 }
209
210 void TreeServer::AddUserCount()
211 {
212         UserCount++;
213 }
214
215 void TreeServer::DelUserCount()
216 {
217         UserCount--;
218 }
219
220 int TreeServer::GetOperCount()
221 {
222         return OperCount;
223 }
224
225 TreeSocket* TreeServer::GetSocket()
226 {
227         return Socket;
228 }
229
230 TreeServer* TreeServer::GetParent()
231 {
232         return Parent;
233 }
234
235 void TreeServer::SetVersion(const std::string &Version)
236 {
237         VersionString = Version;
238 }
239
240 unsigned int TreeServer::ChildCount()
241 {
242         return Children.size();
243 }
244
245 TreeServer* TreeServer::GetChild(unsigned int n)
246 {
247         if (n < Children.size())
248         {
249                 /* Make sure they  cant request
250                  * an out-of-range object. After
251                  * all we know what these programmer
252                  * types are like *grin*.
253                  */
254                 return Children[n];
255         }
256         else
257         {
258                 return NULL;
259         }
260 }
261
262 void TreeServer::AddChild(TreeServer* Child)
263 {
264         Children.push_back(Child);
265 }
266
267 bool TreeServer::DelChild(TreeServer* Child)
268 {
269         for (std::vector<TreeServer*>::iterator a = Children.begin(); a < Children.end(); a++)
270         {
271                 if (*a == Child)
272                 {
273                         Children.erase(a);
274                         return true;
275                 }
276         }
277         return false;
278 }
279
280 /** Removes child nodes of this node, and of that node, etc etc.
281  * This is used during netsplits to automatically tidy up the
282  * server tree. It is slow, we don't use it for much else.
283  */
284 bool TreeServer::Tidy()
285 {
286         bool stillchildren = true;
287         while (stillchildren)
288         {
289                 stillchildren = false;
290                 for (std::vector<TreeServer*>::iterator a = Children.begin(); a < Children.end(); a++)
291                 {
292                         TreeServer* s = (TreeServer*)*a;
293                         s->Tidy();
294                         Children.erase(a);
295                         DELETE(s);
296                         stillchildren = true;
297                         break;
298                 }
299         }
300         return true;
301 }
302
303 TreeServer::~TreeServer()
304 {
305         /* We'd better tidy up after ourselves, eh? */
306         this->DelHashEntry();
307 }
308
309