diff options
-rw-r--r-- | src/modules/m_spanningtree.cpp | 244 |
1 files changed, 85 insertions, 159 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index 2592d2a84..c4708ab38 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -31,6 +31,8 @@ using namespace std; #include "cull_list.h" #include "aes.h" +using irc::sockets::MatchCIDR; + /** If you make a change which breaks the protocol, increment this. * If you completely change the protocol, completely change the number. */ @@ -55,14 +57,7 @@ const long ProtocolVersion = 1101; * any O(n) lookups. If however, during a split or sync, we want * to apply an operation to a server, and any of its child objects * we can resort to recursion to walk the tree structure. - */ - -using irc::sockets::MatchCIDR; - -class ModuleSpanningTree; -static ModuleSpanningTree* TreeProtocolModule; - -/** Any socket can have one of five states at any one time. + * Any socket can have one of five states at any one time. * The LISTENER state indicates a socket which is listening * for connections. It cannot receive data itself, only incoming * sockets. @@ -82,15 +77,13 @@ enum ServerState { LISTENER, CONNECTING, WAIT_AUTH_1, WAIT_AUTH_2, CONNECTED }; /* Foward declarations */ class TreeServer; class TreeSocket; +class Link; +class ModuleSpanningTree; /* This hash_map holds the hash equivalent of the server * tree, used for rapid linear lookups. */ typedef nspace::hash_map<std::string, TreeServer*, nspace::hash<string>, irc::StrHashComp> server_hash; -server_hash serverlist; - -typedef nspace::hash_map<std::string, userrec*> uid_hash; -typedef nspace::hash_map<std::string, char*> sid_hash; /** Contains helper functions and variables for this module, * and keeps them out of the global namespace @@ -100,16 +93,21 @@ class SpanningTreeUtilities private: InspIRCd* ServerInstance; public: + ModuleSpanningTree* Creator; bool FlatLinks; /* Flatten links and /MAP for non-opers */ bool HideULines; /* Hide U-Lined servers in /MAP and /LINKS */ bool AnnounceTSChange; /* Announce TS changes to channels on merge */ std::vector<TreeSocket*> Bindings; /* Socket bindings */ - /* This variable represents the root of the server tree - * (for all intents and purposes, it's us) - */ + /* This variable represents the root of the server tree */ TreeServer *TreeRoot; - - SpanningTreeUtilities(InspIRCd* Instance); + /* IPs allowed to link to us */ + std::vector<std::string> ValidIPs; + /* Hash of currently connected servers by name */ + server_hash serverlist; + /* Holds the data from the <link> tags in the conf */ + std::vector<Link> LinkBlocks; + + SpanningTreeUtilities(InspIRCd* Instance, ModuleSpanningTree* Creator); ~SpanningTreeUtilities(); bool DoOneToOne(std::string prefix, std::string command, std::deque<std::string> ¶ms, std::string target); bool DoOneToAllButSender(std::string prefix, std::string command, std::deque<std::string> ¶ms, std::string omit); @@ -124,58 +122,8 @@ class SpanningTreeUtilities TreeServer* BestRouteTo(std::string ServerName); TreeServer* FindServerMask(std::string ServerName); bool IsServer(std::string ServerName); -}; - - -std::vector<std::string> ValidIPs; - -/** This will be used in a future version of InspIRCd for UID support - */ -class UserManager : public classbase -{ - uid_hash uids; - sid_hash sids; - public: - UserManager() - { - uids.clear(); - sids.clear(); - } - - std::string UserToUID(userrec* user) - { - return ""; - } - - std::string UIDToUser(const std::string &UID) - { - return ""; - } - - std::string CreateAndAdd(userrec* user) - { - return ""; - } - - std::string CreateAndAdd(const std::string &servername) - { - return ""; - } - - std::string ServerToSID(const std::string &servername) - { - return ""; - } - - std::string SIDToServer(const std::string &SID) - { - return ""; - } - - userrec* FindByID(const std::string &UID) - { - return NULL; - } + void DoFailOver(Link* x); + Link* FindLink(const std::string& name); }; @@ -333,10 +281,9 @@ class TreeServer : public classbase */ void AddHashEntry() { - server_hash::iterator iter; - iter = serverlist.find(this->ServerName.c_str()); - if (iter == serverlist.end()) - serverlist[this->ServerName.c_str()] = this; + server_hash::iterator iter = Utils->serverlist.find(this->ServerName.c_str()); + if (iter == Utils->serverlist.end()) + Utils->serverlist[this->ServerName.c_str()] = this; } /** This method removes the reference to this object @@ -345,10 +292,9 @@ class TreeServer : public classbase */ void DelHashEntry() { - server_hash::iterator iter; - iter = serverlist.find(this->ServerName.c_str()); - if (iter != serverlist.end()) - serverlist.erase(iter); + server_hash::iterator iter = Utils->serverlist.find(this->ServerName.c_str()); + if (iter != Utils->serverlist.end()) + Utils->serverlist.erase(iter); } /** These accessors etc should be pretty self- @@ -521,17 +467,6 @@ class Link : public classbase irc::string FailOver; }; -void DoFailOver(Link* x); -Link* FindLink(const std::string& name); - -/* The usual stuff for inspircd modules, - * plus the vector of Link classes which we - * use to store the <link> tags from the config - * file. - */ -ConfigReader *Conf; -std::vector<Link> LinkBlocks; - /** Yay for fast searches! * This is hundreds of times faster than recursion * or even scanning a linked list, especially when @@ -746,7 +681,7 @@ class TreeSocket : public InspSocket if (this->LinkState == CONNECTING) { /* we do not need to change state here. */ - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { if (x->Name == this->myhost) { @@ -788,9 +723,9 @@ class TreeSocket : public InspSocket if (e == I_ERR_CONNECT) { this->Instance->SNO->WriteToSnoMask('l',"Connection failed: Connection to \002"+myhost+"\002 refused"); - Link* MyLink = FindLink(myhost); + Link* MyLink = Utils->FindLink(myhost); if (MyLink) - DoFailOver(MyLink); + Utils->DoFailOver(MyLink); } } @@ -2005,12 +1940,12 @@ class TreeSocket : public InspSocket snprintf(data,MAXBUF,":%s FTOPIC %s %lu %s :%s",sn,c->second->name,(unsigned long)c->second->topicset,c->second->setby,c->second->topic); this->WriteLine(data); } - FOREACH_MOD_I(this->Instance,I_OnSyncChannel,OnSyncChannel(c->second,(Module*)TreeProtocolModule,(void*)this)); + FOREACH_MOD_I(this->Instance,I_OnSyncChannel,OnSyncChannel(c->second,(Module*)Utils->Creator,(void*)this)); list.clear(); c->second->GetExtList(list); for (unsigned int j = 0; j < list.size(); j++) { - FOREACH_MOD_I(this->Instance,I_OnSyncChannelMetaData,OnSyncChannelMetaData(c->second,(Module*)TreeProtocolModule,(void*)this,list[j])); + FOREACH_MOD_I(this->Instance,I_OnSyncChannelMetaData,OnSyncChannelMetaData(c->second,(Module*)Utils->Creator,(void*)this,list[j])); } } } @@ -2035,12 +1970,12 @@ class TreeSocket : public InspSocket { this->WriteLine(":"+std::string(u->second->nick)+" AWAY :"+std::string(u->second->awaymsg)); } - FOREACH_MOD_I(this->Instance,I_OnSyncUser,OnSyncUser(u->second,(Module*)TreeProtocolModule,(void*)this)); + FOREACH_MOD_I(this->Instance,I_OnSyncUser,OnSyncUser(u->second,(Module*)Utils->Creator,(void*)this)); list.clear(); u->second->GetExtList(list); for (unsigned int j = 0; j < list.size(); j++) { - FOREACH_MOD_I(this->Instance,I_OnSyncUserMetaData,OnSyncUserMetaData(u->second,(Module*)TreeProtocolModule,(void*)this,list[j])); + FOREACH_MOD_I(this->Instance,I_OnSyncUserMetaData,OnSyncUserMetaData(u->second,(Module*)Utils->Creator,(void*)this,list[j])); } } } @@ -2068,7 +2003,7 @@ class TreeSocket : public InspSocket /* Send everything else (channel modes, xlines etc) */ this->SendChannelModes(s); this->SendXLines(s); - FOREACH_MOD_I(this->Instance,I_OnSyncOtherMetaData,OnSyncOtherMetaData((Module*)TreeProtocolModule,(void*)this)); + FOREACH_MOD_I(this->Instance,I_OnSyncOtherMetaData,OnSyncOtherMetaData((Module*)Utils->Creator,(void*)this)); this->WriteLine(endburst); this->Instance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+name+"\2."); } @@ -2855,7 +2790,7 @@ class TreeSocket : public InspSocket return false; } std::string description = params[3]; - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { if ((x->Name == servername) && (x->RecvPass == password)) { @@ -2905,7 +2840,7 @@ class TreeSocket : public InspSocket return false; } std::string description = params[3]; - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { if ((x->Name == servername) && (x->RecvPass == password)) { @@ -2979,7 +2914,7 @@ class TreeSocket : public InspSocket if ((!this->ctx_in) && (command == "AES")) { std::string sserv = params[0]; - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { if ((x->EncryptionKey != "") && (x->Name == sserv)) { @@ -3425,9 +3360,9 @@ class TreeSocket : public InspSocket if (this->LinkState == CONNECTING) { this->Instance->SNO->WriteToSnoMask('l',"CONNECT: Connection to \002"+myhost+"\002 timed out."); - Link* MyLink = FindLink(myhost); + Link* MyLink = Utils->FindLink(myhost); if (MyLink) - DoFailOver(MyLink); + Utils->DoFailOver(MyLink); } } @@ -3457,10 +3392,10 @@ class TreeSocket : public InspSocket */ bool found = false; - found = (std::find(ValidIPs.begin(), ValidIPs.end(), ip) != ValidIPs.end()); + found = (std::find(Utils->ValidIPs.begin(), Utils->ValidIPs.end(), ip) != Utils->ValidIPs.end()); if (!found) { - for (vector<std::string>::iterator i = ValidIPs.begin(); i != ValidIPs.end(); i++) + for (vector<std::string>::iterator i = Utils->ValidIPs.begin(); i != Utils->ValidIPs.end(); i++) if (MatchCIDR(ip, (*i).c_str())) found = true; @@ -3517,7 +3452,7 @@ class ServernameResolver : public Resolver /* Something barfed, show the opers */ ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: %s.",MyLink.Name.c_str(),strerror(errno)); delete newsocket; - DoFailOver(&MyLink); + Utils->DoFailOver(&MyLink); } } } @@ -3526,7 +3461,7 @@ class ServernameResolver : public Resolver { /* Ooops! */ ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s",MyLink.Name.c_str(),errormessage.c_str()); - DoFailOver(&MyLink); + Utils->DoFailOver(&MyLink); } }; @@ -3536,15 +3471,16 @@ class SecurityIPResolver : public Resolver { private: Link MyLink; + SpanningTreeUtilities* Utils; public: - SecurityIPResolver(InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), MyLink(x) + SecurityIPResolver(SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), MyLink(x), Utils(U) { } void OnLookupComplete(const std::string &result) { ServerInstance->Log(DEBUG,"Security IP cache: Adding IP address '%s' for Link '%s'",result.c_str(),MyLink.Name.c_str()); - ValidIPs.push_back(result); + Utils->ValidIPs.push_back(result); } void OnError(ResolverError e, const std::string &errormessage) @@ -3553,7 +3489,7 @@ class SecurityIPResolver : public Resolver } }; -SpanningTreeUtilities::SpanningTreeUtilities(InspIRCd* Instance) : ServerInstance(Instance) +SpanningTreeUtilities::SpanningTreeUtilities(InspIRCd* Instance, ModuleSpanningTree* C) : ServerInstance(Instance), Creator(C) { Bindings.clear(); this->TreeRoot = new TreeServer(this, ServerInstance, ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc); @@ -3770,7 +3706,7 @@ bool SpanningTreeUtilities::DoOneToOne(std::string prefix, std::string command, void SpanningTreeUtilities::ReadConfiguration(bool rebind) { - Conf = new ConfigReader(ServerInstance); + ConfigReader* Conf = new ConfigReader(ServerInstance); if (rebind) { for (int j =0; j < Conf->Enumerate("bind"); j++) @@ -3836,7 +3772,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) { try { - SecurityIPResolver* sr = new SecurityIPResolver(ServerInstance, L.IPAddr, L); + SecurityIPResolver* sr = new SecurityIPResolver(this, ServerInstance, L.IPAddr, L); ServerInstance->AddResolver(sr); } catch (ModuleException& e) @@ -3896,7 +3832,7 @@ class ModuleSpanningTree : public Module ModuleSpanningTree(InspIRCd* Me) : Module::Module(Me), max_local(0), max_global(0) { - Utils = new SpanningTreeUtilities(Me); + Utils = new SpanningTreeUtilities(Me, this); command_rconnect = new cmd_rconnect(ServerInstance, this, Utils); ServerInstance->AddCommand(command_rconnect); @@ -3936,7 +3872,7 @@ class ModuleSpanningTree : public Module int CountServs() { - return serverlist.size(); + return Utils->serverlist.size(); } void HandleLinks(const char** parameters, int pcnt, userrec* user) @@ -4284,7 +4220,7 @@ class ModuleSpanningTree : public Module { ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(),strerror(errno)); delete newsocket; - this->DoFailOver(x); + Utils->DoFailOver(x); } } else @@ -4297,48 +4233,14 @@ class ModuleSpanningTree : public Module catch (ModuleException& e) { ServerInstance->Log(DEBUG,"Error in resolver: %s",e.GetReason()); - this->DoFailOver(x); - } - } - } - - void DoFailOver(Link* x) - { - if (x->FailOver.length()) - { - if (x->FailOver == x->Name) - { - ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Some muppet configured the failover for server \002%s\002 to point at itself. Not following it!", x->Name.c_str()); - return; - } - Link* TryThisOne = this->FindLink(x->FailOver.c_str()); - if (TryThisOne) - { - ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Trying failover link for \002%s\002: \002%s\002...", x->Name.c_str(), TryThisOne->Name.c_str()); - ConnectServer(TryThisOne); - } - else - { - ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Invalid failover server specified for server \002%s\002, will not follow!", x->Name.c_str()); - } - } - } - - Link* FindLink(const std::string& name) - { - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) - { - if (ServerInstance->MatchText(x->Name.c_str(), name.c_str())) - { - return &(*x); + Utils->DoFailOver(x); } } - return NULL; } void AutoConnectServers(time_t curtime) { - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { if ((x->AutoConnect) && (curtime >= x->NextConnectTime)) { @@ -4406,7 +4308,7 @@ class ModuleSpanningTree : public Module int HandleConnect(const char** parameters, int pcnt, userrec* user) { - for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { if (ServerInstance->MatchText(x->Name.c_str(),parameters[0])) { @@ -4432,10 +4334,10 @@ class ModuleSpanningTree : public Module { if (statschar == 'c') { - for (unsigned int i = 0; i < LinkBlocks.size(); i++) + for (unsigned int i = 0; i < Utils->LinkBlocks.size(); i++) { - results.push_back(std::string(ServerInstance->Config->ServerName)+" 213 "+user->nick+" C *@"+(LinkBlocks[i].HiddenFromStats ? "<hidden>" : LinkBlocks[i].IPAddr)+" * "+LinkBlocks[i].Name.c_str()+" "+ConvToStr(LinkBlocks[i].Port)+" "+(LinkBlocks[i].EncryptionKey != "" ? 'e' : '-')+(LinkBlocks[i].AutoConnect ? 'a' : '-')+'s'); - results.push_back(std::string(ServerInstance->Config->ServerName)+" 244 "+user->nick+" H * * "+LinkBlocks[i].Name.c_str()); + results.push_back(std::string(ServerInstance->Config->ServerName)+" 213 "+user->nick+" C *@"+(Utils->LinkBlocks[i].HiddenFromStats ? "<hidden>" : Utils->LinkBlocks[i].IPAddr)+" * "+Utils->LinkBlocks[i].Name.c_str()+" "+ConvToStr(Utils->LinkBlocks[i].Port)+" "+(Utils->LinkBlocks[i].EncryptionKey != "" ? 'e' : '-')+(Utils->LinkBlocks[i].AutoConnect ? 'a' : '-')+'s'); + results.push_back(std::string(ServerInstance->Config->ServerName)+" 244 "+user->nick+" H * * "+Utils->LinkBlocks[i].Name.c_str()); } results.push_back(std::string(ServerInstance->Config->ServerName)+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); ServerInstance->SNO->WriteToSnoMask('t',"Notice: %s '%c' requested by %s (%s@%s)",(!strcmp(user->server,ServerInstance->Config->ServerName) ? "Stats" : "Remote stats"),statschar,user->nick,user->ident,user->host); @@ -5069,16 +4971,41 @@ class ModuleSpanningTree : public Module } }; -void DoFailOver(Link* x) +void SpanningTreeUtilities::DoFailOver(Link* x) { - TreeProtocolModule->DoFailOver(x); + if (x->FailOver.length()) + { + if (x->FailOver == x->Name) + { + ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Some muppet configured the failover for server \002%s\002 to point at itself. Not following it!", x->Name.c_str()); + return; + } + Link* TryThisOne = this->FindLink(x->FailOver.c_str()); + if (TryThisOne) + { + ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Trying failover link for \002%s\002: \002%s\002...", x->Name.c_str(), TryThisOne->Name.c_str()); + Creator->ConnectServer(TryThisOne); + } + else + { + ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Invalid failover server specified for server \002%s\002, will not follow!", x->Name.c_str()); + } + } } -Link* FindLink(const std::string& name) +Link* SpanningTreeUtilities::FindLink(const std::string& name) { - return TreeProtocolModule->FindLink(name); + for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++) + { + if (ServerInstance->MatchText(x->Name.c_str(), name.c_str())) + { + return &(*x); + } + } + return NULL; } + class ModuleSpanningTreeFactory : public ModuleFactory { public: @@ -5092,8 +5019,7 @@ class ModuleSpanningTreeFactory : public ModuleFactory virtual Module * CreateModule(InspIRCd* Me) { - TreeProtocolModule = new ModuleSpanningTree(Me); - return TreeProtocolModule; + return new ModuleSpanningTree(Me); } }; |