summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-30 21:55:31 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-30 21:55:31 +0000
commit78aabc62e7510af5075b2056f703f0aa42e328a4 (patch)
tree6b166da1ec2a6f8682a2588f0651fedd34ebf1db /src
parent3dc81ee1331d1b37ee85be9bf0d843e3b6827a2d (diff)
Allow multiple autoconnects in a single <autoconnect> tag, fix infinite failover
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11786 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src')
-rw-r--r--src/modules/m_spanningtree/handshaketimer.h2
-rw-r--r--src/modules/m_spanningtree/link.h19
-rw-r--r--src/modules/m_spanningtree/main.cpp69
-rw-r--r--src/modules/m_spanningtree/main.h6
-rw-r--r--src/modules/m_spanningtree/override_stats.cpp4
-rw-r--r--src/modules/m_spanningtree/resolvers.cpp19
-rw-r--r--src/modules/m_spanningtree/resolvers.h19
-rw-r--r--src/modules/m_spanningtree/server.cpp6
-rw-r--r--src/modules/m_spanningtree/treesocket.h2
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp7
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp2
-rw-r--r--src/modules/m_spanningtree/utils.cpp136
-rw-r--r--src/modules/m_spanningtree/utils.h24
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<Link> 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 <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
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<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
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 ? "<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;
}
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<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);
};
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 &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;
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<Autoconnect> 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<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));
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<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;
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<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);