]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Allow multiple autoconnects in a single <autoconnect> tag, fix infinite failover
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 30 Sep 2009 21:55:31 +0000 (21:55 +0000)
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 30 Sep 2009 21:55:31 +0000 (21:55 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11786 e03df62e-2008-0410-955e-edbf42e46eb7

13 files changed:
src/modules/m_spanningtree/handshaketimer.h
src/modules/m_spanningtree/link.h
src/modules/m_spanningtree/main.cpp
src/modules/m_spanningtree/main.h
src/modules/m_spanningtree/override_stats.cpp
src/modules/m_spanningtree/resolvers.cpp
src/modules/m_spanningtree/resolvers.h
src/modules/m_spanningtree/server.cpp
src/modules/m_spanningtree/treesocket.h
src/modules/m_spanningtree/treesocket1.cpp
src/modules/m_spanningtree/treesocket2.cpp
src/modules/m_spanningtree/utils.cpp
src/modules/m_spanningtree/utils.h

index 3f01a8b5bbeda9e68cb774a0a2fbd1fa8621112a..527b056bc2cd2b6a0870838fd9f2155c38612d3e 100644 (file)
@@ -25,7 +25,7 @@ class HandshakeTimer : public Timer
 {
  private:
        TreeSocket* sock;
-       Link* lnk;
+       reference<Link> lnk;
        SpanningTreeUtilities* Utils;
        int thefd;
  public:
index d7630cac30fe2012819e5f690a7196de633a7cf4..ae7655ebbb84d0e4c90b08b92ae80b45bcd70989 100644 (file)
 #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 <link>
- * 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<std::string> servers;
+       unsigned long Period;
+       time_t NextConnectTime;
+       /** Negative == inactive */
+       int position;
+};
+
+
 #endif
index 501baa2904bd5b1dbdd68bfc1704daaa2d4ff40b..4442ae78475caa5a8b69bf0e0af982bff24a9f68 100644 (file)
@@ -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<Autoconnect>::iterator x = Utils->AutoconnectBlocks.begin(); x < Utils->AutoconnectBlocks.end(); ++x)
+       for (std::vector<reference<Autoconnect> >::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<Autoconnect*>::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<std::string>& parameters, User* user)
 {
-       for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
+       for (std::vector<reference<Link> >::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<std::string>& para
                        if (!CheckDupe)
                        {
                                RemoteMessage(user, "*** CONNECT: Connecting to server: \002%s\002 (%s:%d)",x->Name.c_str(),(x->HiddenFromStats ? "<hidden>" : x->IPAddr.c_str()),x->Port);
-                               ConnectServer(&(*x), NULL);
+                               ConnectServer(x);
                                return MOD_RES_DENY;
                        }
                        else
index 429c0d4bd398330c738c92233e4838ffadf132b3..fc3392e264b2b42e8c50003fc3190244c3841a1a 100644 (file)
@@ -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
         */
index 5d0239f8463754fb9856bf438a916d36a2c97868..93190a978d01f1c28ee31b2a24120f033577aa9d 100644 (file)
@@ -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 ? "<hidden>" : 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 ? "<hidden>" : 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;
        }
index 782c7795d620a9628fcdbadbbbcc01866b896317..e168b98f5667ed4bd123971b82c3ce6517cfc437 100644 (file)
@@ -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);
 }
 
index 5b5bf88ccf1c51346a61c226dbec9bcefc2c2f06..29ead13de2ffed539dcbaef9a0f13ae1be92d4d0 100644 (file)
 class SecurityIPResolver : public Resolver
 {
  private:
-       Link MyLink;
+       reference<Link> 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<Link> MyLink;
+       reference<Autoconnect> 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);
 };
index b1c6c2cb45f3c30b7fdc6b46fdf7ac96bafb82d5..900aceb9dfde62ee11a97c014082487eae0539a9 100644 (file)
@@ -120,8 +120,9 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist &params)
                return false;
        }
 
-       for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
+       for (std::vector<reference<Link> >::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 &params)
                return false;
        }
 
-       for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
+       for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); i++)
        {
+               Link* x = *i;
                if (x->Name != servername && x->Name != "*") // open link allowance
                        continue;
 
index 3c94849818f1f177327e7b08b8de3b362d0acc8a..520026a99db9d264ea8504c7770a217da5d696f6 100644 (file)
@@ -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<Autoconnect> myautoconnect;           /* Autoconnect used to cause this connection, if any */
        time_t age;
 
        /** Because most of the I/O gubbins are encapsulated within
index 6bb736a853acd4fc2767edf47e4b5be1791211cd..46effe48cd4f6fc35a912c054b4a73f679e71d61 100644 (file)
@@ -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<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
+               for (std::vector<reference<Link> >::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 ? "<hidden>" : 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));
index 1b617804e459f65ddd3ea9aa101b81bb4a3bacbe..928f8e262d1e88404927a192f201841f9711fd88 100644 (file)
@@ -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);
        }
 }
 
index 6f94ead60ed9021de4761aa5162adf5eafbf08b5..5091859e1d5b7816f9941fcac15943a8de299bef 100644 (file)
@@ -383,8 +383,9 @@ bool SpanningTreeUtilities::DoOneToOne(const std::string &prefix, const std::str
 void SpanningTreeUtilities::RefreshIPCache()
 {
        ValidIPs.clear();
-       for (std::vector<Link>::iterator L = LinkBlocks.begin(); L != LinkBlocks.end(); L++)
+       for (std::vector<reference<Link> >::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<Link> 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 <link> 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 <link> 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<Autoconnect> 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<Link>::iterator x = LinkBlocks.begin(); x != LinkBlocks.end(); x++)
+       for (std::vector<reference<Link> >::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;
index d1922ed751791f609f245fc9b11b5380d5a95fab..a80b60e46a005b2288e8993c1ea4d24292e5dcfc 100644 (file)
@@ -20,6 +20,7 @@
 class TreeServer;
 class TreeSocket;
 class Link;
+class Autoconnect;
 class ModuleSpanningTree;
 class SpanningTreeUtilities;
 
@@ -62,21 +63,6 @@ typedef std::map<TreeServer*,TreeServer*> TreeServerList;
  */
 typedef std::map<irc::string, Module*> 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 <autoconnect>
- * 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<TreeSocket*, std::pair<std::string, int> > timeoutlist;
        /** Holds the data from the <link> tags in the conf
         */
-       std::vector<Link> LinkBlocks;
+       std::vector<reference<Link> > LinkBlocks;
        /** Holds the data from the <autoconnect> tags in the conf
         */
-       std::vector<Autoconnect> AutoconnectBlocks;
+       std::vector<reference<Autoconnect> > 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);