From 78aabc62e7510af5075b2056f703f0aa42e328a4 Mon Sep 17 00:00:00 2001 From: danieldg Date: Wed, 30 Sep 2009 21:55:31 +0000 Subject: [PATCH] Allow multiple autoconnects in a single tag, fix infinite failover git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11786 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/modules/m_spanningtree/handshaketimer.h | 2 +- src/modules/m_spanningtree/link.h | 19 ++- src/modules/m_spanningtree/main.cpp | 69 +++++---- src/modules/m_spanningtree/main.h | 6 +- src/modules/m_spanningtree/override_stats.cpp | 4 +- src/modules/m_spanningtree/resolvers.cpp | 19 +-- src/modules/m_spanningtree/resolvers.h | 19 ++- src/modules/m_spanningtree/server.cpp | 6 +- src/modules/m_spanningtree/treesocket.h | 2 +- src/modules/m_spanningtree/treesocket1.cpp | 7 +- src/modules/m_spanningtree/treesocket2.cpp | 2 +- src/modules/m_spanningtree/utils.cpp | 136 ++++++++---------- src/modules/m_spanningtree/utils.h | 24 +--- 13 files changed, 150 insertions(+), 165 deletions(-) diff --git a/src/modules/m_spanningtree/handshaketimer.h b/src/modules/m_spanningtree/handshaketimer.h index 3f01a8b5b..527b056bc 100644 --- a/src/modules/m_spanningtree/handshaketimer.h +++ b/src/modules/m_spanningtree/handshaketimer.h @@ -25,7 +25,7 @@ class HandshakeTimer : public Timer { private: TreeSocket* sock; - Link* lnk; + reference lnk; SpanningTreeUtilities* Utils; int thefd; public: diff --git a/src/modules/m_spanningtree/link.h b/src/modules/m_spanningtree/link.h index d7630cac3..ae7655ebb 100644 --- a/src/modules/m_spanningtree/link.h +++ b/src/modules/m_spanningtree/link.h @@ -14,13 +14,7 @@ #ifndef __LINK_H__ #define __LINK_H__ -/** The Link class might as well be a struct, - * but this is C++ and we don't believe in structs (!). - * It holds the entire information of one - * tag from the main config file. We maintain a list - * of them, and populate the list on rehash/load. - */ -class Link : public classbase +class Link : public refcountbase { public: irc::string Name; @@ -37,4 +31,15 @@ class Link : public classbase bool Hidden; }; +class Autoconnect : public refcountbase +{ + public: + std::vector servers; + unsigned long Period; + time_t NextConnectTime; + /** Negative == inactive */ + int position; +}; + + #endif diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 501baa290..4442ae784 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -244,6 +244,25 @@ void ModuleSpanningTree::DoPingChecks(time_t curtime) } } +void ModuleSpanningTree::ConnectServer(Autoconnect* y) +{ + y->position++; + while (y->position < (int)y->servers.size()) + { + Link* x = Utils->FindLink(y->servers[y->position]); + if (x) + { + ServerInstance->SNO->WriteToSnoMask('l', "AUTOCONNECT: Auto-connecting server \002%s\002", x->Name.c_str()); + ConnectServer(x, y); + return; + } + y->position++; + } + // Autoconnect chain has been fully iterated; start at the beginning on the + // next AutoConnectServers run + y->position = -1; +} + void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y) { bool ipvalid = true; @@ -284,7 +303,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y) { ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(),strerror(errno)); ServerInstance->GlobalCulls.AddItem(newsocket); - Utils->DoFailOver(y); + ConnectServer(y); } } else @@ -292,45 +311,41 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y) try { bool cached; - ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, x->IPAddr, *x, cached, start_type, y); + ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, x->IPAddr, x, cached, start_type, y); ServerInstance->AddResolver(snr, cached); } catch (ModuleException& e) { ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(), e.GetReason()); - Utils->DoFailOver(y); + ConnectServer(y); } } } void ModuleSpanningTree::AutoConnectServers(time_t curtime) { - for (std::vector::iterator x = Utils->AutoconnectBlocks.begin(); x < Utils->AutoconnectBlocks.end(); ++x) + for (std::vector >::iterator i = Utils->AutoconnectBlocks.begin(); i < Utils->AutoconnectBlocks.end(); ++i) { + Autoconnect* x = *i; if (curtime >= x->NextConnectTime) { x->NextConnectTime = curtime + x->Period; - TreeServer* CheckDupe = Utils->FindServer(x->Server.c_str()); - Link* y = Utils->FindLink(x->Server); - if (x->FailOver.length()) + for(unsigned int j=0; j < x->servers.size(); j++) { - TreeServer* CheckFailOver = Utils->FindServer(x->FailOver.c_str()); - if (CheckFailOver) + if (Utils->FindServer(x->servers[j])) { - /* The failover for this server is currently a member of the network. - * The failover probably succeeded, where the main link did not. - * Don't try the main link until the failover is gone again. - */ - continue; + // found something in this block. Should the server fail, + // we want to start at the start of the list, not in the + // middle where we left off + x->position = -1; + goto dupe_found; // next autoconnect block } } - if (!CheckDupe) - { - // an autoconnected server is not connected. Check if its time to connect it - ServerInstance->SNO->WriteToSnoMask('l',"AUTOCONNECT: Auto-connecting server \002%s\002 (%lu seconds until next attempt)",y->Name.c_str(),x->Period); - this->ConnectServer(&(*y), &(*x)); - } + // only start a new chain if we aren't running + if (x->position == -1) + ConnectServer(x); } +dupe_found:; } } @@ -344,15 +359,14 @@ void ModuleSpanningTree::DoConnectTimeout(time_t curtime) if (curtime > s->age + p.second) { ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002 (timeout of %d seconds)",p.first.c_str(),p.second); - failovers.push_back(s->myautoconnect); - ServerInstance->SE->DelFd(s); + if (s->myautoconnect) + failovers.push_back(s->myautoconnect); s->Close(); } } - /* Trigger failover for each timed out socket */ - for (std::vector::const_iterator n = failovers.begin(); n != failovers.end(); ++n) + for(unsigned int i=0; i < failovers.size(); i++) { - Utils->DoFailOver(*n); + ConnectServer(failovers[i]); } } @@ -395,8 +409,9 @@ void ModuleSpanningTree::RemoteMessage(User* user, const char* format, ...) ModResult ModuleSpanningTree::HandleConnect(const std::vector& parameters, User* user) { - for (std::vector::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) + for (std::vector >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); i++) { + Link* x = *i; if (InspIRCd::Match(x->Name.c_str(),parameters[0])) { if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name))) @@ -409,7 +424,7 @@ ModResult ModuleSpanningTree::HandleConnect(const std::vector& para if (!CheckDupe) { RemoteMessage(user, "*** CONNECT: Connecting to server: \002%s\002 (%s:%d)",x->Name.c_str(),(x->HiddenFromStats ? "" : x->IPAddr.c_str()),x->Port); - ConnectServer(&(*x), NULL); + ConnectServer(x); return MOD_RES_DENY; } else diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h index 429c0d4bd..fc3392e26 100644 --- a/src/modules/m_spanningtree/main.h +++ b/src/modules/m_spanningtree/main.h @@ -124,7 +124,11 @@ class ModuleSpanningTree : public Module /** Connect a server locally */ - void ConnectServer(Link* x, Autoconnect* y); + void ConnectServer(Link* x, Autoconnect* y = NULL); + + /** Connect the next autoconnect server + */ + void ConnectServer(Autoconnect* y); /** Check if any servers are due to be autoconnected */ diff --git a/src/modules/m_spanningtree/override_stats.cpp b/src/modules/m_spanningtree/override_stats.cpp index 5d0239f84..93190a978 100644 --- a/src/modules/m_spanningtree/override_stats.cpp +++ b/src/modules/m_spanningtree/override_stats.cpp @@ -60,9 +60,9 @@ ModResult ModuleSpanningTree::OnStats(char statschar, User* user, string_list &r { for (unsigned int i = 0; i < Utils->LinkBlocks.size(); i++) { - results.push_back(std::string(ServerInstance->Config->ServerName)+" 213 "+user->nick+" "+statschar+" *@"+(Utils->LinkBlocks[i].HiddenFromStats ? "" : Utils->LinkBlocks[i].IPAddr)+" * "+Utils->LinkBlocks[i].Name.c_str()+" "+ConvToStr(Utils->LinkBlocks[i].Port)+" "+(Utils->LinkBlocks[i].Hook.empty() ? "plaintext" : Utils->LinkBlocks[i].Hook)); + results.push_back(std::string(ServerInstance->Config->ServerName)+" 213 "+user->nick+" "+statschar+" *@"+(Utils->LinkBlocks[i]->HiddenFromStats ? "" : Utils->LinkBlocks[i]->IPAddr)+" * "+Utils->LinkBlocks[i]->Name.c_str()+" "+ConvToStr(Utils->LinkBlocks[i]->Port)+" "+(Utils->LinkBlocks[i]->Hook.empty() ? "plaintext" : Utils->LinkBlocks[i]->Hook)); if (statschar == 'c') - 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)+" 244 "+user->nick+" H * * "+Utils->LinkBlocks[i]->Name.c_str()); } return MOD_RES_DENY; } diff --git a/src/modules/m_spanningtree/resolvers.cpp b/src/modules/m_spanningtree/resolvers.cpp index 782c7795d..e168b98f5 100644 --- a/src/modules/m_spanningtree/resolvers.cpp +++ b/src/modules/m_spanningtree/resolvers.cpp @@ -31,7 +31,8 @@ * callback to OnLookupComplete or OnError when completed. Once it has completed we * will have an IP address which we can then use to continue our connection. */ -ServernameResolver::ServernameResolver(Module* me, SpanningTreeUtilities* Util, const std::string &hostname, Link x, bool &cached, QueryType qt, Autoconnect* myac) : Resolver(hostname, qt, cached, me), MyLink(x), Utils(Util), query(qt), host(hostname), mine(me), myautoconnect(myac) +ServernameResolver::ServernameResolver(Module* me, SpanningTreeUtilities* Util, const std::string &hostname, Link* x, bool &cached, QueryType qt, Autoconnect* myac) + : Resolver(hostname, qt, cached, me), Utils(Util), query(qt), host(hostname), mine(me), MyLink(x), myautoconnect(myac) { /* Nothing in here, folks */ } @@ -42,15 +43,15 @@ void ServernameResolver::OnLookupComplete(const std::string &result, unsigned in * Passing a hostname directly to BufferedSocket causes it to * just bail and set its FD to -1. */ - TreeServer* CheckDupe = Utils->FindServer(MyLink.Name.c_str()); + TreeServer* CheckDupe = Utils->FindServer(MyLink->Name.c_str()); if (!CheckDupe) /* Check that nobody tried to connect it successfully while we were resolving */ { - if ((!MyLink.Hook.empty()) && (Utils->hooks.find(MyLink.Hook.c_str()) == Utils->hooks.end())) + if ((!MyLink->Hook.empty()) && (Utils->hooks.find(MyLink->Hook.c_str()) == Utils->hooks.end())) return; - TreeSocket* newsocket = new TreeSocket(this->Utils, result,MyLink.Port,MyLink.Timeout ? MyLink.Timeout : 10,MyLink.Name.c_str(), - MyLink.Bind, myautoconnect, MyLink.Hook.empty() ? NULL : Utils->hooks[MyLink.Hook.c_str()]); + TreeSocket* newsocket = new TreeSocket(this->Utils, result,MyLink->Port,MyLink->Timeout ? MyLink->Timeout : 10,MyLink->Name.c_str(), + MyLink->Bind, myautoconnect, MyLink->Hook.empty() ? NULL : Utils->hooks[MyLink->Hook.c_str()]); if (newsocket->GetFd() > -1) { /* We're all OK */ @@ -58,9 +59,9 @@ void ServernameResolver::OnLookupComplete(const std::string &result, unsigned in else { /* Something barfed, show the opers */ - ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",MyLink.Name.c_str(),strerror(errno)); + ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",MyLink->Name.c_str(),strerror(errno)); ServerInstance->GlobalCulls.AddItem(newsocket); - Utils->DoFailOver(myautoconnect); + Utils->Creator->ConnectServer(myautoconnect); } } } @@ -75,7 +76,7 @@ void ServernameResolver::OnError(ResolverError e, const std::string &errormessag ServerInstance->AddResolver(snr, cached); return; } - ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s", MyLink.Name.c_str(), errormessage.c_str() ); - Utils->DoFailOver(myautoconnect); + ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s", MyLink->Name.c_str(), errormessage.c_str() ); + Utils->Creator->ConnectServer(myautoconnect); } diff --git a/src/modules/m_spanningtree/resolvers.h b/src/modules/m_spanningtree/resolvers.h index 5b5bf88cc..29ead13de 100644 --- a/src/modules/m_spanningtree/resolvers.h +++ b/src/modules/m_spanningtree/resolvers.h @@ -27,13 +27,13 @@ class SecurityIPResolver : public Resolver { private: - Link MyLink; + reference MyLink; SpanningTreeUtilities* Utils; Module* mine; std::string host; QueryType query; public: - SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link x, bool &cached, QueryType qt) + SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt) : Resolver(hostname, qt, cached, me), MyLink(x), Utils(U), mine(me), host(hostname), query(qt) { } @@ -52,7 +52,8 @@ class SecurityIPResolver : public Resolver ServerInstance->AddResolver(res, cached); return; } - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Could not resolve IP associated with Link '%s': %s",MyLink.Name.c_str(),errormessage.c_str()); + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Could not resolve IP associated with Link '%s': %s", + MyLink->Name.c_str(),errormessage.c_str()); } }; @@ -65,18 +66,14 @@ class SecurityIPResolver : public Resolver class ServernameResolver : public Resolver { private: - /** A copy of the Link tag info for what we're connecting to. - * We take a copy, rather than using a pointer, just in case the - * admin takes the tag away and rehashes while the domain is resolving. - */ - Link MyLink; - SpanningTreeUtilities* Utils; + SpanningTreeUtilities* Utils; QueryType query; std::string host; Module* mine; - Autoconnect* myautoconnect; + reference MyLink; + reference myautoconnect; public: - ServernameResolver(Module* me, SpanningTreeUtilities* Util, const std::string &hostname, Link x, bool &cached, QueryType qt, Autoconnect* myac); + ServernameResolver(Module* me, SpanningTreeUtilities* Util, const std::string &hostname, Link* x, bool &cached, QueryType qt, Autoconnect* myac); void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached); void OnError(ResolverError e, const std::string &errormessage); }; diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp index b1c6c2cb4..900aceb9d 100644 --- a/src/modules/m_spanningtree/server.cpp +++ b/src/modules/m_spanningtree/server.cpp @@ -120,8 +120,9 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) return false; } - for (std::vector::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) + for (std::vector >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); i++) { + Link* x = *i; if (x->Name != servername && x->Name != "*") // open link allowance continue; @@ -215,8 +216,9 @@ bool TreeSocket::Inbound_Server(parameterlist ¶ms) return false; } - for (std::vector::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) + for (std::vector >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); i++) { + Link* x = *i; if (x->Name != servername && x->Name != "*") // open link allowance continue; diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 3c9484981..520026a99 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -92,7 +92,7 @@ class TreeSocket : public BufferedSocket int proto_version; /* Remote protocol version */ public: HandshakeTimer* hstimer; /* Handshake timer, needed to work around I/O hook buffering */ - Autoconnect* myautoconnect; /* Autoconnect used to cause this connection, if any */ + reference myautoconnect; /* Autoconnect used to cause this connection, if any */ time_t age; /** Because most of the I/O gubbins are encapsulated within diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 6bb736a85..46effe48c 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -66,7 +66,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, int newfd, char* ip, Autocon if (HookMod) BufferedSocketHookRequest(this, Utils->Creator, HookMod).Send(); - hstimer = new HandshakeTimer(this, &(Utils->LinkBlocks[0]), this->Utils, 1); + hstimer = new HandshakeTimer(this, Utils->LinkBlocks[0], this->Utils, 1); ServerInstance->Timers->AddTimer(hstimer); /* Fix by Brain - inbound sockets need a timeout, too. 30 secs should be pleanty */ @@ -108,8 +108,9 @@ void TreeSocket::OnConnected() if (this->LinkState == CONNECTING) { /* we do not need to change state here. */ - for (std::vector::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) + for (std::vector >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); ++i) { + Link* x = *i; if (x->Name == this->myhost) { ServerInstance->SNO->WriteToSnoMask('l', "Connection to \2%s\2[%s] started.", myhost.c_str(), (x->HiddenFromStats ? "" : this->IP.c_str())); @@ -140,7 +141,7 @@ void TreeSocket::OnError(BufferedSocketError e) { case I_ERR_CONNECT: ServerInstance->SNO->WriteToSnoMask('l', "Connection failed: Connection to \002%s\002 refused", myhost.c_str()); - Utils->DoFailOver(myautoconnect); + Utils->Creator->ConnectServer(myautoconnect); break; case I_ERR_SOCKET: ServerInstance->SNO->WriteToSnoMask('l', "Connection failed: Could not create socket (%s)", strerror(errno)); diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 1b617804e..928f8e262 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -606,7 +606,7 @@ void TreeSocket::OnTimeout() if (this->LinkState == CONNECTING) { ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str()); - Utils->DoFailOver(myautoconnect); + Utils->Creator->ConnectServer(myautoconnect); } } diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index 6f94ead60..5091859e1 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -383,8 +383,9 @@ bool SpanningTreeUtilities::DoOneToOne(const std::string &prefix, const std::str void SpanningTreeUtilities::RefreshIPCache() { ValidIPs.clear(); - for (std::vector::iterator L = LinkBlocks.begin(); L != LinkBlocks.end(); L++) + for (std::vector >::iterator i = LinkBlocks.begin(); i != LinkBlocks.end(); ++i) { + Link* L = *i; if (L->IPAddr.empty() || L->RecvPass.empty() || L->SendPass.empty() || L->Name.empty() || !L->Port) { if (L->Name.empty()) @@ -427,7 +428,7 @@ void SpanningTreeUtilities::RefreshIPCache() try { bool cached; - SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, L->IPAddr, *L, cached, start_type); + SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, L->IPAddr, L, cached, start_type); ServerInstance->AddResolver(sr, cached); } catch (...) @@ -529,55 +530,55 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) ValidIPs.clear(); for (int j = 0; j < Conf->Enumerate("link"); ++j) { - Link L; + reference L = new Link; std::string Allow = Conf->ReadValue("link", "allowmask", j); - L.Name = (Conf->ReadValue("link", "name", j)).c_str(); - L.AllowMask = Allow; - L.IPAddr = Conf->ReadValue("link", "ipaddr", j); - L.Port = Conf->ReadInteger("link", "port", j, true); - L.SendPass = Conf->ReadValue("link", "sendpass", j); - L.RecvPass = Conf->ReadValue("link", "recvpass", j); - L.Fingerprint = Conf->ReadValue("link", "fingerprint", j); - L.HiddenFromStats = Conf->ReadFlag("link", "statshidden", j); - L.Timeout = Conf->ReadInteger("link", "timeout", j, true); - L.Hook = Conf->ReadValue("link", "transport", j); - L.Bind = Conf->ReadValue("link", "bind", j); - L.Hidden = Conf->ReadFlag("link", "hidden", j); - - if ((!L.Hook.empty()) && (hooks.find(L.Hook.c_str()) == hooks.end())) + L->Name = (Conf->ReadValue("link", "name", j)).c_str(); + L->AllowMask = Allow; + L->IPAddr = Conf->ReadValue("link", "ipaddr", j); + L->Port = Conf->ReadInteger("link", "port", j, true); + L->SendPass = Conf->ReadValue("link", "sendpass", j); + L->RecvPass = Conf->ReadValue("link", "recvpass", j); + L->Fingerprint = Conf->ReadValue("link", "fingerprint", j); + L->HiddenFromStats = Conf->ReadFlag("link", "statshidden", j); + L->Timeout = Conf->ReadInteger("link", "timeout", j, true); + L->Hook = Conf->ReadValue("link", "transport", j); + L->Bind = Conf->ReadValue("link", "bind", j); + L->Hidden = Conf->ReadFlag("link", "hidden", j); + + if ((!L->Hook.empty()) && (hooks.find(L->Hook.c_str()) == hooks.end())) { - throw CoreException("Can't find transport type '"+L.Hook+"' for link '"+assign(L.Name)+"' - maybe you forgot to load it BEFORE m_spanningtree in your config file? Skipping tag completely."); + throw CoreException("Can't find transport type '"+L->Hook+"' for link '"+assign(L->Name)+"' - maybe you forgot to load it BEFORE m_spanningtree in your config file? Skipping tag completely."); continue; } - if (L.Name.find('.') == std::string::npos) - throw CoreException("The link name '"+assign(L.Name)+"' is invalid and must contain at least one '.' character"); + if (L->Name.find('.') == std::string::npos) + throw CoreException("The link name '"+assign(L->Name)+"' is invalid and must contain at least one '.' character"); - if (L.Name.length() > 64) - throw CoreException("The link name '"+assign(L.Name)+"' is longer than 64 characters!"); + if (L->Name.length() > 64) + throw CoreException("The link name '"+assign(L->Name)+"' is longer than 64 characters!"); - if ((!L.IPAddr.empty()) && (!L.RecvPass.empty()) && (!L.SendPass.empty()) && (!L.Name.empty()) && (L.Port)) + if ((!L->IPAddr.empty()) && (!L->RecvPass.empty()) && (!L->SendPass.empty()) && (!L->Name.empty()) && (L->Port)) { if (Allow.length()) ValidIPs.push_back(Allow); - ValidIPs.push_back(L.IPAddr); + ValidIPs.push_back(L->IPAddr); /* Needs resolving */ bool ipvalid = true; QueryType start_type = DNS_QUERY_A; start_type = DNS_QUERY_AAAA; - if (strchr(L.IPAddr.c_str(),':')) + if (strchr(L->IPAddr.c_str(),':')) { in6_addr n; - if (inet_pton(AF_INET6, L.IPAddr.c_str(), &n) < 1) + if (inet_pton(AF_INET6, L->IPAddr.c_str(), &n) < 1) ipvalid = false; } else { in_addr n; - if (inet_aton(L.IPAddr.c_str(),&n) < 1) + if (inet_aton(L->IPAddr.c_str(),&n) < 1) ipvalid = false; } @@ -586,7 +587,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) try { bool cached; - SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, L.IPAddr, L, cached, start_type); + SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, L->IPAddr, L, cached, start_type); ServerInstance->AddResolver(sr, cached); } catch (...) @@ -596,31 +597,31 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) } else { - if (L.IPAddr.empty()) + if (L->IPAddr.empty()) { - L.IPAddr = "*"; + L->IPAddr = "*"; ValidIPs.push_back("*"); - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block " + assign(L.Name) + " has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want."); + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block " + assign(L->Name) + " has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want."); } - if (L.RecvPass.empty()) + if (L->RecvPass.empty()) { - throw CoreException("Invalid configuration for server '"+assign(L.Name)+"', recvpass not defined!"); + throw CoreException("Invalid configuration for server '"+assign(L->Name)+"', recvpass not defined!"); } - if (L.SendPass.empty()) + if (L->SendPass.empty()) { - throw CoreException("Invalid configuration for server '"+assign(L.Name)+"', sendpass not defined!"); + throw CoreException("Invalid configuration for server '"+assign(L->Name)+"', sendpass not defined!"); } - if (L.Name.empty()) + if (L->Name.empty()) { - throw CoreException("Invalid configuration, link tag without a name! IP address: "+L.IPAddr); + throw CoreException("Invalid configuration, link tag without a name! IP address: "+L->IPAddr); } - if (!L.Port) + if (!L->Port) { - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block " + assign(L.Name) + " has no port defined, you will not be able to /connect it."); + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block " + assign(L->Name) + " has no port defined, you will not be able to /connect it."); } } @@ -629,21 +630,27 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) for (int j = 0; j < Conf->Enumerate("autoconnect"); ++j) { - Autoconnect A; - A.Period = Conf->ReadInteger("autoconnect", "period", j, true); - A.Server = Conf->ReadValue("autoconnect", "server", j); - A.FailOver = Conf->ReadValue("autoconnect", "failover", j).c_str(); + reference A = new Autoconnect; + A->Period = Conf->ReadInteger("autoconnect", "period", j, true); + A->position = -1; + std::string servers = Conf->ReadValue("autoconnect", "server", j); + irc::spacesepstream ss(servers); + std::string server; + while (ss.GetToken(server)) + { + A->servers.push_back(server); + } // Fix: Only trip autoconnects if this wouldn't delay autoconnect.. - if (A.NextConnectTime > ((time_t)(ServerInstance->Time() + A.Period))) - A.NextConnectTime = ServerInstance->Time() + A.Period; + if (A->NextConnectTime > ((time_t)(ServerInstance->Time() + A->Period))) + A->NextConnectTime = ServerInstance->Time() + A->Period; - if (A.Period <= 0) + if (A->Period <= 0) { throw CoreException("Invalid configuration for autoconnect, period not a positive integer!"); } - if (A.Server.empty()) + if (A->servers.empty()) { throw CoreException("Invalid configuration for autoconnect, server cannot be empty!"); } @@ -654,43 +661,14 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) delete Conf; } -void SpanningTreeUtilities::DoFailOver(Autoconnect* x) -{ - if (x && x->FailOver.length()) - { - if (x->FailOver == x->Server) - { - ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Some muppet configured the failover for server \002%s\002 to point at itself. Not following it!", x->Server.c_str()); - return; - } - Link* TryThisOne = this->FindLink(x->FailOver.c_str()); - if (TryThisOne) - { - TreeServer* CheckDupe = this->FindServer(x->FailOver.c_str()); - if (CheckDupe) - { - ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Skipping existing failover: %s", x->FailOver.c_str()); - } - else - { - ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Trying failover link for \002%s\002: \002%s\002...", x->Server.c_str(), TryThisOne->Name.c_str()); - Creator->ConnectServer(TryThisOne, NULL); - } - } - else - { - ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Invalid failover server specified for server \002%s\002, will not follow!", x->Server.c_str()); - } - } -} - Link* SpanningTreeUtilities::FindLink(const std::string& name) { - for (std::vector::iterator x = LinkBlocks.begin(); x != LinkBlocks.end(); x++) + for (std::vector >::iterator i = LinkBlocks.begin(); i != LinkBlocks.end(); ++i) { + Link* x = *i; if (InspIRCd::Match(x->Name.c_str(), name.c_str())) { - return &(*x); + return x; } } return NULL; diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index d1922ed75..a80b60e46 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -20,6 +20,7 @@ class TreeServer; class TreeSocket; class Link; +class Autoconnect; class ModuleSpanningTree; class SpanningTreeUtilities; @@ -62,21 +63,6 @@ typedef std::map TreeServerList; */ typedef std::map hookmodules; -/** The Autoconnect class might as well be a struct, - * but this is C++ and we don't believe in structs (!). - * It holds the entire information of one - * tag from the main config file. We maintain a list - * of them, and populate the list on rehash/load. - */ -class Autoconnect : public classbase -{ - public: - unsigned long Period; - std::string Server; - time_t NextConnectTime; - std::string FailOver; -}; - /** Contains helper functions and variables for this module, * and keeps them out of the global namespace */ @@ -135,10 +121,10 @@ class SpanningTreeUtilities : public classbase std::map > timeoutlist; /** Holds the data from the tags in the conf */ - std::vector LinkBlocks; + std::vector > LinkBlocks; /** Holds the data from the tags in the conf */ - std::vector AutoconnectBlocks; + std::vector > AutoconnectBlocks; /** List of module pointers which can provide I/O abstraction */ @@ -228,10 +214,6 @@ class SpanningTreeUtilities : public classbase */ bool IsServer(const std::string &ServerName); - /** Attempt to connect to the failover link of link x - */ - void DoFailOver(Autoconnect* x); - /** Find a link tag from a server name */ Link* FindLink(const std::string& name); -- 2.39.5