summaryrefslogtreecommitdiff
path: root/src/modules/m_spanningtree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/m_spanningtree.cpp')
-rw-r--r--src/modules/m_spanningtree.cpp163
1 files changed, 97 insertions, 66 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index 4f25b01d3..395644772 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -491,17 +491,21 @@ class TreeServer : public classbase
class Link : public classbase
{
public:
- irc::string Name;
- std::string IPAddr;
- int Port;
- std::string SendPass;
- std::string RecvPass;
- unsigned long AutoConnect;
- time_t NextConnectTime;
- std::string EncryptionKey;
- bool HiddenFromStats;
+ irc::string Name;
+ std::string IPAddr;
+ int Port;
+ std::string SendPass;
+ std::string RecvPass;
+ unsigned long AutoConnect;
+ time_t NextConnectTime;
+ std::string EncryptionKey;
+ bool HiddenFromStats;
+ irc::string FailOver;
};
+void DoFailOver(Link* x);
+Link* FindLink(const std::string& name);
+
/* The usual stuff for inspircd modules,
* plus the vector of Link classes which we
* use to store the <link> tags from the config
@@ -754,7 +758,10 @@ class TreeSocket : public InspSocket
*/
if (e == I_ERR_CONNECT)
{
- this->Instance->SNO->WriteToSnoMask('l',"Connection failed: Connection refused");
+ this->Instance->SNO->WriteToSnoMask('l',"Connection failed: Connection to \002"+myhost+"\002 refused");
+ Link* MyLink = FindLink(myhost);
+ if (MyLink)
+ DoFailOver(MyLink);
}
}
@@ -3222,6 +3229,9 @@ class TreeSocket : public InspSocket
if (this->LinkState == CONNECTING)
{
this->Instance->SNO->WriteToSnoMask('l',"CONNECT: Connection to \002"+myhost+"\002 timed out.");
+ Link* MyLink = FindLink(myhost);
+ if (MyLink)
+ DoFailOver(MyLink);
}
}
@@ -3310,6 +3320,7 @@ class ServernameResolver : public Resolver
/* Something barfed, show the opers */
ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: %s.",MyLink.Name.c_str(),strerror(errno));
delete newsocket;
+ DoFailOver(&MyLink);
}
}
}
@@ -3318,6 +3329,7 @@ class ServernameResolver : public Resolver
{
/* Ooops! */
ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s",MyLink.Name.c_str(),errormessage.c_str());
+ DoFailOver(&MyLink);
}
};
@@ -3571,6 +3583,7 @@ void ReadConfiguration(bool rebind)
std::string Allow = Conf->ReadValue("link","allowmask",j);
L.Name = (Conf->ReadValue("link","name",j)).c_str();
L.IPAddr = Conf->ReadValue("link","ipaddr",j);
+ L.FailOver = Conf->ReadValue("link","failover",j).c_str();
L.Port = Conf->ReadInteger("link","port",j,true);
L.SendPass = Conf->ReadValue("link","sendpass",j);
L.RecvPass = Conf->ReadValue("link","recvpass",j);
@@ -4033,6 +4046,69 @@ class ModuleSpanningTree : public Module
}
}
+ void ConnectServer(Link* x)
+ {
+ insp_inaddr binip;
+
+ /* Do we already have an IP? If so, no need to resolve it. */
+ if (insp_aton(x->IPAddr.c_str(), &binip) > 0)
+ {
+ TreeSocket* newsocket = new TreeSocket(ServerInstance, x->IPAddr,x->Port,false,10,x->Name.c_str());
+ if (newsocket->GetFd() > -1)
+ {
+ /* Handled automatically on success */
+ }
+ else
+ {
+ ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(),strerror(errno));
+ delete newsocket;
+ this->DoFailOver(x);
+ }
+ }
+ else
+ {
+ try
+ {
+ ServernameResolver* snr = new ServernameResolver(ServerInstance,x->IPAddr, *x);
+ ServerInstance->AddResolver(snr);
+ }
+ catch (ModuleException& e)
+ {
+ ServerInstance->Log(DEBUG,"Error in resolver: %s",e.GetReason());
+ this->DoFailOver(x);
+ }
+ }
+ }
+
+ void DoFailOver(Link* x)
+ {
+ if (x->FailOver.length())
+ {
+ Link* TryThisOne = this->FindLink(x->FailOver.c_str());
+ if (TryThisOne)
+ {
+ ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Trying failover link for \002%s\002: \002%s\002...", x->Name.c_str(), TryThisOne->Name.c_str());
+ ConnectServer(TryThisOne);
+ }
+ else
+ {
+ ServerInstance->SNO->WriteToSnoMask('l',"FAILOVER: Invalid failover server specified for server \002%s\002, will not follow!", x->Name.c_str());
+ }
+ }
+ }
+
+ Link* FindLink(const std::string& name)
+ {
+ for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++)
+ {
+ if (ServerInstance->MatchText(x->Name.c_str(), name.c_str()))
+ {
+ return &(*x);
+ }
+ }
+ return NULL;
+ }
+
void AutoConnectServers(time_t curtime)
{
for (std::vector<Link>::iterator x = LinkBlocks.begin(); x < LinkBlocks.end(); x++)
@@ -4046,35 +4122,7 @@ class ModuleSpanningTree : public Module
{
// 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)",x->Name.c_str(),x->AutoConnect);
-
- insp_inaddr binip;
-
- /* Do we already have an IP? If so, no need to resolve it. */
- if (insp_aton(x->IPAddr.c_str(), &binip) > 0)
- {
- TreeSocket* newsocket = new TreeSocket(ServerInstance, x->IPAddr,x->Port,false,10,x->Name.c_str());
- if (newsocket->GetFd() > -1)
- {
- }
- else
- {
- ServerInstance->SNO->WriteToSnoMask('l',"AUTOCONNECT: Error autoconnecting \002%s\002: %s.",x->Name.c_str(),strerror(errno));
- delete newsocket;
- }
- }
- else
- {
- try
- {
- ServernameResolver* snr = new ServernameResolver(ServerInstance,x->IPAddr, *x);
- ServerInstance->AddResolver(snr);
- }
- catch (ModuleException& e)
- {
- ServerInstance->Log(DEBUG,"Error in resolver: %s",e.GetReason());
- }
- }
-
+ this->ConnectServer(&(*x));
}
}
}
@@ -4127,33 +4175,7 @@ class ModuleSpanningTree : public Module
if (!CheckDupe)
{
user->WriteServ("NOTICE %s :*** CONNECT: Connecting to server: \002%s\002 (%s:%d)",user->nick,x->Name.c_str(),(x->HiddenFromStats ? "<hidden>" : x->IPAddr.c_str()),x->Port);
- insp_inaddr binip;
-
- /* Do we already have an IP? If so, no need to resolve it. */
- if (insp_aton(x->IPAddr.c_str(), &binip) > 0)
- {
- TreeSocket* newsocket = new TreeSocket(ServerInstance,x->IPAddr,x->Port,false,10,x->Name.c_str());
- if (newsocket->GetFd() > -1)
- {
- }
- else
- {
- ServerInstance->SNO->WriteToSnoMask('l',"CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(),strerror(errno));
- delete newsocket;
- }
- }
- else
- {
- try
- {
- ServernameResolver* snr = new ServernameResolver(ServerInstance, x->IPAddr, *x);
- ServerInstance->AddResolver(snr);
- }
- catch (ModuleException& e)
- {
- ServerInstance->Log(DEBUG,"Error in resolver: %s",e.GetReason());
- }
- }
+ ConnectServer(&(*x));
return 1;
}
else
@@ -4801,6 +4823,15 @@ class ModuleSpanningTree : public Module
}
};
+void DoFailOver(Link* x)
+{
+ TreeProtocolModule->DoFailOver(x);
+}
+
+Link* FindLink(const std::string& name)
+{
+ return TreeProtocolModule->FindLink(name);
+}
class ModuleSpanningTreeFactory : public ModuleFactory
{