Anope IRC Services  Version 2.0
servers.cpp
Go to the documentation of this file.
1 /* Routines to maintain a list of connected servers
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  */
12 
13 #include "services.h"
14 #include "modules.h"
15 #include "xline.h"
16 #include "servers.h"
17 #include "bots.h"
18 #include "regchannel.h"
19 #include "protocol.h"
20 #include "config.h"
21 #include "channels.h"
22 
23 /* Anope */
24 Server *Me = NULL;
25 
28 
29 std::set<Anope::string> Servers::Capab;
30 
31 Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Anope::string &desc, const Anope::string &ssid, bool jupe) : name(sname), hops(shops), description(desc), sid(ssid), uplink(up), users(0)
32 {
33  syncing = true;
34  juped = jupe;
35  quitting = false;
36 
37  Servers::ByName[sname] = this;
38  if (!ssid.empty())
39  Servers::ByID[ssid] = this;
40 
41  Log(this, "connect") << "has connected to the network (uplinked to " << (this->uplink ? this->uplink->GetName() : "no uplink") << ")";
42 
43  /* Add this server to our uplinks leaf list */
44  if (this->uplink)
45  {
46  this->uplink->AddLink(this);
47 
48  /* Check to be sure this isn't a juped server */
49  if (Me == this->uplink && !juped)
50  {
51  /* Now do mode related stuff as we know what modes exist .. */
52  for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
53  {
54  BotInfo *bi = it->second;
56 
57  bi->SetModesInternal(bi, modes.c_str());
58  for (unsigned i = 0; i < bi->botchannels.size(); ++i)
59  {
60  size_t h = bi->botchannels[i].find('#');
61  if (h == Anope::string::npos)
62  continue;
63  Anope::string chname = bi->botchannels[i].substr(h);
64  Channel *c = Channel::Find(chname);
65  if (c && c->FindUser(bi))
66  {
67  Anope::string want_modes = bi->botchannels[i].substr(0, h);
68  for (unsigned j = 0; j < want_modes.length(); ++j)
69  {
71  if (cm == NULL)
73  if (cm && cm->type == MODE_STATUS)
74  {
75  MessageSource ms = bi;
76  c->SetModeInternal(ms, cm, bi->nick);
77  }
78  }
79  }
80  }
81  }
82 
83  IRCD->SendBOB();
84 
85  for (unsigned i = 0; i < Me->GetLinks().size(); ++i)
86  {
87  Server *s = Me->GetLinks()[i];
88 
89  if (s->juped)
90  IRCD->SendServer(s);
91  }
92 
93  /* We make the bots go online */
94  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
95  {
96  User *u = it->second;
97 
98  BotInfo *bi = BotInfo::Find(u->GetUID());
99  if (bi)
100  {
101  XLine x(bi->nick, "Reserved for services");
102  IRCD->SendSQLine(NULL, &x);
103  }
104 
106  if (bi)
107  bi->introduced = true;
108  }
109 
110  for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
111  {
112  Channel *c = it->second;
113 
114  if (c->users.empty())
115  IRCD->SendChannel(c);
116  else
117  for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit)
118  IRCD->SendJoin(cit->second->user, c, &cit->second->status);
119 
120  for (Channel::ModeList::const_iterator it2 = c->GetModes().begin(); it2 != c->GetModes().end(); ++it2)
121  {
123  if (!cm || cm->type != MODE_LIST)
124  continue;
125  ModeManager::StackerAdd(c->ci->WhoSends(), c, cm, true, it2->second);
126  }
127 
128  if (!c->topic.empty() && !c->topic_setter.empty())
129  IRCD->SendTopic(c->ci->WhoSends(), c);
130 
131  c->syncing = true;
132  }
133  }
134  }
135 
136  FOREACH_MOD(OnNewServer, (this));
137 }
138 
140 {
141  Log(this, "quit") << "quit from " << (this->uplink ? this->uplink->GetName() : "no uplink") << " for " << this->quit_reason;
142 
143  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
144  {
145  User *u = it->second;
146 
147  if (u->server == this)
148  {
149  u->Quit(this->quit_reason);
150  u->server = NULL;
151  }
152  }
153 
154  Log(LOG_DEBUG) << "Finished removing all users for " << this->GetName();
155 
156  if (this->uplink)
157  this->uplink->DelLink(this);
158 
159  for (unsigned i = this->links.size(); i > 0; --i)
160  this->links[i - 1]->Delete(this->quit_reason);
161 
162  Servers::ByName.erase(this->name);
163  if (!this->sid.empty())
164  Servers::ByID.erase(this->sid);
165 }
166 
167 void Server::Delete(const Anope::string &reason)
168 {
169  this->quit_reason = reason;
170  this->quitting = true;
171  FOREACH_MOD(OnServerQuit, (this));
172  delete this;
173 }
174 
176 {
177  return this->name;
178 }
179 
180 unsigned Server::GetHops() const
181 {
182  return this->hops;
183 }
184 
186 {
187  this->description = desc;
188 }
189 
191 {
192  return this->description;
193 }
194 
195 void Server::SetSID(const Anope::string &nsid)
196 {
197  if (!this->sid.empty())
198  throw CoreException("Server already has an id?");
199  this->sid = nsid;
200  Servers::ByID[nsid] = this;
201 }
202 
204 {
205  if (!this->sid.empty() && IRCD->RequiresID)
206  return this->sid;
207  else
208  return this->name;
209 }
210 
212 {
213  return this->quit_reason;
214 }
215 
216 const std::vector<Server *> &Server::GetLinks() const
217 {
218  return this->links;
219 }
220 
222 {
223  return this->uplink;
224 }
225 
227 {
228  this->links.push_back(s);
229 
230  Log(this, "connect") << "introduced " << s->GetName();
231 }
232 
234 {
235  if (this->links.empty())
236  throw CoreException("Server::DelLink called on " + this->GetName() + " for " + s->GetName() + " but we have no links?");
237 
238  for (unsigned i = 0, j = this->links.size(); i < j; ++i)
239  {
240  if (this->links[i] == s)
241  {
242  this->links.erase(this->links.begin() + i);
243  break;
244  }
245  }
246 
247  Log(this, "quit") << "quit " << s->GetName();
248 }
249 
250 void Server::Sync(bool sync_links)
251 {
252  if (this->IsSynced())
253  return;
254 
255  syncing = false;
256 
257  Log(this, "sync") << "is done syncing";
258 
259  FOREACH_MOD(OnServerSync, (this));
260 
261  if (sync_links && !this->links.empty())
262  {
263  for (unsigned i = 0, j = this->links.size(); i < j; ++i)
264  this->links[i]->Sync(true);
265  }
266 
267  bool me = this->GetUplink() && this->GetUplink() == Me;
268 
269  if (me)
270  {
271  FOREACH_MOD(OnPreUplinkSync, (this));
272  }
273 
274  for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end;)
275  {
276  Channel *c = it->second;
277  ++it;
278 
279  if (c->syncing)
280  c->Sync();
281  }
282 
283  if (me)
284  {
285  IRCD->SendEOB();
286  Me->Sync(false);
287 
288  FOREACH_MOD(OnUplinkSync, (this));
289 
290  if (!Anope::NoFork && Anope::AtTerm())
291  {
292  Log(LOG_TERMINAL) << "Successfully linked, launching into background...";
293  Anope::Fork();
294  }
295  }
296 }
297 
298 bool Server::IsSynced() const
299 {
300  return !syncing;
301 }
302 
304 {
305  syncing = true;
306 }
307 
308 bool Server::IsULined() const
309 {
310  if (this == Me)
311  return true;
312 
313  for (unsigned i = 0; i < Config->Ulines.size(); ++i)
314  if (Config->Ulines[i].equals_ci(this->GetName()))
315  return true;
316  return false;
317 }
318 
319 bool Server::IsJuped() const
320 {
321  return juped;
322 }
323 
324 bool Server::IsQuitting() const
325 {
326  return quitting;
327 }
328 
329 void Server::Notice(BotInfo *source, const Anope::string &message)
330 {
331  if (Config->UsePrivmsg && Config->DefPrivmsg)
332  IRCD->SendGlobalPrivmsg(source, this, message);
333  else
334  IRCD->SendGlobalNotice(source, this, message);
335 }
336 
337 Server *Server::Find(const Anope::string &name, bool name_only)
338 {
340 
341  if (!name_only)
342  {
343  it = Servers::ByID.find(name);
344  if (it != Servers::ByID.end())
345  return it->second;
346  }
347 
348  it = Servers::ByName.find(name);
349  if (it != Servers::ByName.end())
350  return it->second;
351 
352  return NULL;
353 }
354 
356 {
357  for (unsigned i = 0; Me && i < Me->GetLinks().size(); ++i)
358  if (!Me->GetLinks()[i]->IsJuped())
359  return Me->GetLinks()[i];
360  return NULL;
361 }
362 
Definition: bots.h:24
void Notice(BotInfo *source, const Anope::string &message)
Definition: servers.cpp:329
Definition: servers.h:42
std::vector< Anope::string > botchannels
Definition: bots.h:37
bool quitting
Definition: servers.h:62
const ModeList & GetModes() const
Definition: channels.cpp:238
static ChannelMode * FindChannelModeByName(const Anope::string &name)
Definition: modes.cpp:542
bool IsSynced() const
Definition: servers.cpp:298
unsigned GetHops() const
Definition: servers.cpp:180
bool IsQuitting() const
Definition: servers.cpp:324
CoreExport Anope::map< Server * > ByID
Definition: servers.cpp:27
Anope::string desc
Definition: access.cpp:23
void DelLink(Server *s)
Definition: servers.cpp:233
void Quit(const Anope::string &reason="")
Definition: users.cpp:749
CoreExport std::set< Anope::string > Capab
Definition: servers.cpp:29
Anope::string botmodes
Definition: bots.h:35
virtual void SendTopic(const MessageSource &, Channel *)
Definition: protocol.cpp:170
const Anope::string & GetSID() const
Definition: servers.cpp:203
void AddLink(Server *s)
Definition: servers.cpp:226
Definition: users.h:34
Anope::string topic_setter
Definition: channels.h:61
bool AtTerm()
Definition: init.cpp:98
Anope::string DefaultPseudoclientModes
Definition: protocol.h:47
Server * uplink
Definition: servers.h:56
bool introduced
Definition: bots.h:39
virtual void SendSQLine(User *, const XLine *x)
Definition: protocol.h:120
bool IsJuped() const
Definition: servers.cpp:319
Server(Server *uplink, const Anope::string &name, unsigned hops, const Anope::string &description, const Anope::string &sid="", bool jupe=false)
Definition: servers.cpp:31
void SetSID(const Anope::string &sid)
Definition: servers.cpp:195
Anope::string quit_reason
Definition: servers.h:64
unsigned int hops
Definition: servers.h:48
Anope::string description
Definition: servers.h:50
Serialize::Reference< ChannelInfo > ci
Definition: channels.h:46
bool RequiresID
Definition: protocol.h:69
CoreExport Server * GetUplink()
Definition: servers.cpp:355
Anope::string topic
Definition: channels.h:59
void Sync(bool sync_links)
Definition: servers.cpp:250
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
bool juped
Definition: servers.h:60
static Module * me
Definition: bs_kick.cpp:18
void Fork()
Definition: init.cpp:103
Server * Me
Definition: servers.cpp:24
size_type length() const
Definition: anope.h:131
ModeType type
Definition: modes.h:49
Definition: Config.cs:26
CoreExport Anope::map< Server * > ByName
Definition: servers.cpp:26
static char GetStatusChar(char symbol)
Definition: modes.cpp:558
const Anope::string & GetQuitReason() const
Definition: servers.cpp:211
std::vector< Server * > links
Definition: servers.h:54
static const size_type npos
Definition: anope.h:44
virtual void SendBOB()
Definition: protocol.h:203
const Anope::string & GetUID() const
Definition: users.cpp:230
CoreExport Serialize::Checker< botinfo_map > BotListByNick
Anope::string sid
Definition: servers.h:52
static ChannelMode * FindChannelModeByChar(char mode)
Definition: modes.cpp:524
virtual void SendServer(const Server *)=0
static Anope::map< std::pair< bool, Anope::string > > modes
Definition: cs_mode.cpp:745
bool empty() const
Definition: anope.h:126
void SetModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:251
static Server * Find(const Anope::string &name, bool name_only=false)
Definition: servers.cpp:337
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
Server * server
Definition: users.h:77
CoreExport channel_map ChannelList
Definition: channels.cpp:29
ChanUserList users
Definition: channels.h:56
ChanUserContainer * FindUser(User *u) const
Definition: channels.cpp:173
virtual void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg)=0
const std::vector< Server * > & GetLinks() const
Definition: servers.cpp:216
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const Anope::string &param="")
Definition: modes.cpp:607
void Unsync()
Definition: servers.cpp:303
Anope::string nick
Definition: users.h:62
const Anope::string & GetDescription() const
Definition: servers.cpp:190
virtual void SendChannel(Channel *c)
Definition: protocol.h:224
const Anope::string & GetName() const
Definition: servers.cpp:175
bool syncing
Definition: channels.h:50
static Channel * Find(const Anope::string &name)
Definition: channels.cpp:920
Definition: xline.h:18
bool syncing
Definition: servers.h:58
virtual void SendClientIntroduction(User *u)=0
Anope::string name
Definition: access.cpp:22
CoreExport user_map UserListByNick
Definition: users.cpp:28
void SetModesInternal(const MessageSource &source, const char *umodes,...)
Definition: users.cpp:645
CoreExport bool NoFork
Definition: main.cpp:28
virtual void SendEOB()
Definition: protocol.h:204
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
virtual void SendJoin(User *u, Channel *c, const ChannelStatus *status)=0
bool IsULined() const
Definition: servers.cpp:308
void SetDescription(const Anope::string &desc)
Definition: servers.cpp:185
virtual void SendGlobalPrivmsg(BotInfo *bi, const Server *desc, const Anope::string &msg)=0
Anope::string name
Definition: servers.h:46
void Sync()
Definition: channels.cpp:98
static BotInfo * Find(const Anope::string &nick, bool nick_only=false)
Definition: bots.cpp:249
~Server()
Definition: servers.cpp:139
void Delete(const Anope::string &reason)
Definition: servers.cpp:167
Server * GetUplink()
Definition: servers.cpp:221