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