00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "services.h"
00014 #include "modules.h"
00015 #include "xline.h"
00016 #include "servers.h"
00017 #include "bots.h"
00018 #include "regchannel.h"
00019 #include "protocol.h"
00020 #include "config.h"
00021 #include "channels.h"
00022
00023
00024 Server *Me = NULL;
00025
00026 std::set<Anope::string> Servers::Capab;
00027
00028 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)
00029 {
00030 syncing = true;
00031 juped = jupe;
00032
00033 Log(this, "connect") << "uplinked to " << (this->uplink ? this->uplink->GetName() : "no uplink") << " connected to the network";
00034
00035
00036 if (this->uplink)
00037 {
00038 this->uplink->AddLink(this);
00039
00040
00041 if (Me == this->uplink && !juped)
00042 {
00043
00044 for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
00045 {
00046 BotInfo *bi = it->second;
00047 Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : IRCD->DefaultPseudoclientModes;
00048
00049 bi->SetModesInternal(modes.c_str());
00050 for (unsigned i = 0; i < bi->botchannels.size(); ++i)
00051 {
00052 size_t h = bi->botchannels[i].find('#');
00053 if (h == Anope::string::npos)
00054 continue;
00055 Anope::string chname = bi->botchannels[i].substr(h);
00056 Channel *c = Channel::Find(chname);
00057 if (c && c->FindUser(bi))
00058 {
00059 Anope::string want_modes = bi->botchannels[i].substr(0, h);
00060 for (unsigned j = 0; j < want_modes.length(); ++j)
00061 {
00062 ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]);
00063 if (cm == NULL)
00064 cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
00065 if (cm && cm->type == MODE_STATUS)
00066 {
00067 MessageSource ms = bi;
00068 c->SetModeInternal(ms, cm, bi->nick);
00069 }
00070 }
00071 }
00072 }
00073 }
00074
00075 IRCD->SendBOB();
00076
00077 for (unsigned i = 0; i < Me->GetLinks().size(); ++i)
00078 {
00079 Server *s = Me->GetLinks()[i];
00080
00081 if (s->juped)
00082 IRCD->SendServer(s);
00083 }
00084
00085
00086 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
00087 {
00088 User *u = it->second;
00089
00090 BotInfo *bi = BotInfo::Find(u->nick);
00091 if (bi)
00092 {
00093 XLine x(bi->nick, "Reserved for services");
00094 IRCD->SendSQLine(NULL, &x);
00095 }
00096
00097 IRCD->SendClientIntroduction(u);
00098 if (bi)
00099 bi->introduced = true;
00100 }
00101
00102 for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
00103 {
00104 Channel *c = it->second;
00105 if (c->users.empty())
00106 IRCD->SendChannel(c);
00107 else
00108 for (User::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit)
00109 IRCD->SendJoin((*cit)->user, c, &(*cit)->status);
00110 }
00111 }
00112 }
00113
00114 FOREACH_MOD(I_OnNewServer, OnNewServer(this));
00115 }
00116
00117 Server::~Server()
00118 {
00119 Log(this, "quit") << "quit from " << (this->uplink ? this->uplink->GetName() : "no uplink") << " for " << this->quit_reason;
00120
00121 if (Servers::Capab.count("NOQUIT") > 0 || Servers::Capab.count("QS") > 0)
00122 {
00123 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();)
00124 {
00125 User *u = it->second;
00126 ++it;
00127
00128 if (u->server == this)
00129 {
00130 NickAlias *na = NickAlias::Find(u->nick);
00131 if (na && !na->nc->HasExt("SUSPENDED") && (u->IsRecognized() || u->IsIdentified()))
00132 {
00133 na->last_seen = Anope::CurTime;
00134 if (!Config->NSHideNetSplitQuit)
00135 na->last_quit = this->quit_reason;
00136 }
00137
00138 u->Quit(this->quit_reason);
00139 u->server = NULL;
00140 }
00141 }
00142
00143 Log(LOG_DEBUG) << "Finished removing all users for " << this->GetName();
00144 }
00145
00146 if (this->uplink)
00147 this->uplink->DelLink(this);
00148
00149 for (unsigned i = this->links.size(); i > 0; --i)
00150 this->links[i - 1]->Delete(this->quit_reason);
00151 }
00152
00153 void Server::Delete(const Anope::string &reason)
00154 {
00155 this->quit_reason = reason;
00156 FOREACH_MOD(I_OnServerQuit, OnServerQuit(this));
00157 delete this;
00158 }
00159
00160 const Anope::string &Server::GetName() const
00161 {
00162 return this->name;
00163 }
00164
00165 unsigned Server::GetHops() const
00166 {
00167 return this->hops;
00168 }
00169
00170 void Server::SetDescription(const Anope::string &desc)
00171 {
00172 this->description = desc;
00173 }
00174
00175 const Anope::string &Server::GetDescription() const
00176 {
00177 return this->description;
00178 }
00179
00180 void Server::SetSID(const Anope::string &nsid)
00181 {
00182 this->sid = nsid;
00183 }
00184
00185 const Anope::string &Server::GetSID() const
00186 {
00187 if (!this->sid.empty() && IRCD->RequiresID)
00188 return this->sid;
00189 else
00190 return this->name;
00191 }
00192
00193 const std::vector<Server *> &Server::GetLinks() const
00194 {
00195 return this->links;
00196 }
00197
00198 Server *Server::GetUplink()
00199 {
00200 return this->uplink;
00201 }
00202
00203 void Server::AddLink(Server *s)
00204 {
00205 this->links.push_back(s);
00206
00207 Log(this, "connect") << "introduced " << s->GetName();
00208 }
00209
00210 void Server::DelLink(Server *s)
00211 {
00212 if (this->links.empty())
00213 throw CoreException("Server::DelLink called on " + this->GetName() + " for " + s->GetName() + " but we have no links?");
00214
00215 for (unsigned i = 0, j = this->links.size(); i < j; ++i)
00216 {
00217 if (this->links[i] == s)
00218 {
00219 this->links.erase(this->links.begin() + i);
00220 break;
00221 }
00222 }
00223
00224 Log(this, "quit") << "quit " << s->GetName();
00225 }
00226
00227 void Server::Sync(bool sync_links)
00228 {
00229 if (this->IsSynced())
00230 return;
00231
00232 syncing = false;
00233
00234 Log(this, "sync") << "is done syncing";
00235
00236 FOREACH_MOD(I_OnServerSync, OnServerSync(this));
00237
00238 if (sync_links && !this->links.empty())
00239 {
00240 for (unsigned i = 0, j = this->links.size(); i < j; ++i)
00241 this->links[i]->Sync(true);
00242 }
00243
00244 if (this->GetUplink() && this->GetUplink() == Me)
00245 {
00246 for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
00247 {
00248 ChannelInfo *ci = it->second;
00249 if (ci->HasExt("PERSIST"))
00250 {
00251 bool created = false;
00252 if (!ci->c)
00253 {
00254 ci->c = new Channel(ci->name, ci->time_registered);
00255 created = true;
00256 }
00257 if (ModeManager::FindChannelModeByName("PERM") != NULL)
00258 {
00259 ci->c->SetMode(NULL, "PERM");
00260 if (created)
00261 IRCD->SendChannel(ci->c);
00262 }
00263 else
00264 {
00265 if (!ci->bi)
00266 ci->WhoSends()->Assign(NULL, ci);
00267 if (ci->c->FindUser(ci->bi) == NULL)
00268 ci->bi->Join(ci->c);
00269 }
00270 }
00271 }
00272
00273 FOREACH_MOD(I_OnPreUplinkSync, OnPreUplinkSync(this));
00274
00275 IRCD->SendEOB();
00276 Me->Sync(false);
00277
00278 FOREACH_MOD(I_OnUplinkSync, OnUplinkSync(this));
00279
00280 for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
00281 {
00282 Channel *c = it->second;
00283 c->Sync();
00284 }
00285
00286 if (!Anope::NoFork && Anope::AtTerm())
00287 {
00288 Log(LOG_TERMINAL) << "Successfully linked, launching into background...";
00289 Anope::Fork();
00290 }
00291 }
00292 }
00293
00294 bool Server::IsSynced() const
00295 {
00296 return !syncing;
00297 }
00298
00299 void Server::Unsync()
00300 {
00301 syncing = true;
00302 }
00303
00304 bool Server::IsULined() const
00305 {
00306 if (this == Me)
00307 return true;
00308
00309 for (std::list<Anope::string>::const_iterator it = Config->Ulines.begin(), it_end = Config->Ulines.end(); it != it_end; ++it)
00310 if (it->equals_ci(this->GetName()))
00311 return true;
00312 return false;
00313 }
00314
00315 bool Server::IsJuped() const
00316 {
00317 return juped;
00318 }
00319
00320 void Server::Notice(const BotInfo *source, const Anope::string &message)
00321 {
00322 if (Config->NSDefFlags.count("MSG"))
00323 IRCD->SendGlobalPrivmsg(source, this, message);
00324 else
00325 IRCD->SendGlobalNotice(source, this, message);
00326 }
00327
00328 Server *Server::Find(const Anope::string &name, Server *s)
00329 {
00330 Log(LOG_DEBUG_2) << "Server::Find called for " << name;
00331
00332 if (!s)
00333 s = Me;
00334 if (s->GetName().equals_ci(name) || s->GetSID().equals_cs(name))
00335 return s;
00336
00337 if (!s->GetLinks().empty())
00338 {
00339 for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i)
00340 {
00341 Server *serv = s->GetLinks()[i];
00342
00343 if (serv->GetName().equals_ci(name) || serv->GetSID().equals_cs(name))
00344 return serv;
00345 Log(LOG_DEBUG_2) << "Server::Find checking " << serv->GetName() << " server tree for " << name;
00346 Server *server = Server::Find(name, serv);
00347 if (server)
00348 return server;
00349 }
00350 }
00351
00352 return NULL;
00353 }
00354
00355
00356
00357 static inline char& nextID(char &c)
00358 {
00359 if (c == 'Z')
00360 c = '0';
00361 else if (c != '9')
00362 ++c;
00363 else
00364 c = 'A';
00365 return c;
00366 }
00367
00368 const Anope::string Servers::TS6_UID_Retrieve()
00369 {
00370 if (!IRCD || !IRCD->RequiresID)
00371 return "";
00372
00373 static Anope::string current_uid = "AAAAAA";
00374
00375 while (User::Find(Config->Numeric + current_uid) != NULL)
00376 {
00377 int current_len = current_uid.length() - 1;
00378 while (current_len >= 0 && nextID(current_uid[current_len--]) == 'A');
00379 }
00380
00381 return Config->Numeric + current_uid;
00382 }
00383
00384 const Anope::string Servers::TS6_SID_Retrieve()
00385 {
00386 if (!IRCD || !IRCD->RequiresID)
00387 return "";
00388
00389 static Anope::string current_sid;
00390 if (current_sid.empty())
00391 {
00392 current_sid = Config->Numeric;
00393 if (current_sid.empty())
00394 current_sid = "00A";
00395 }
00396
00397 while (Server::Find(current_sid) != NULL)
00398 {
00399 int current_len = current_sid.length() - 1;
00400 while (current_len >= 0 && nextID(current_sid[current_len--]) == 'A');
00401 }
00402
00403 return current_sid;
00404 }
00405
00406 Server* Servers::GetUplink()
00407 {
00408 for (unsigned i = 0; Me && i < Me->GetLinks().size(); ++i)
00409 if (!Me->GetLinks()[i]->IsJuped())
00410 return Me->GetLinks()[i];
00411 return NULL;
00412 }
00413