From 9d5ac7988dc35df8a927e4984a979291be88c183 Mon Sep 17 00:00:00 2001 From: brain Date: Mon, 4 Sep 2006 23:25:28 +0000 Subject: failover connections are now added, thanks for the idea Lauren (happy now? lol) :) git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@5141 e03df62e-2008-0410-955e-edbf42e46eb7 --- docs/inspircd.conf.example | 19 +++++ src/modules/m_spanningtree.cpp | 163 ++++++++++++++++++++++++----------------- 2 files changed, 116 insertions(+), 66 deletions(-) diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example index 2c31849e1..ca06d0dc9 100644 --- a/docs/inspircd.conf.example +++ b/docs/inspircd.conf.example @@ -399,6 +399,24 @@ # into this value. If it is not defined, then only # # the ipaddr field of the server shall be allowed. # # # +# failover - If you define this option, it must be the name of a # +# different link tag in your configuration. This # +# option causes the ircd to attempt a connection to # +# the failover link in the event that the connection # +# to this server fails. For example, you could define # +# two hub uplinks to a leaf server, and set an # +# american server to autoconnect, with a european # +# hub as its failover. In this situation, your ircd # +# will only try the link to the european hub if the # +# american hub is unreachable. NOTE that for the # +# intents and purposes of this option, an unreachable # +# server is one which DOES NOT ANSWER THE CONNECTION. # +# If the server answers the connection with accept(), # +# EVEN IF THE CREDENTIALS ARE INVALID, the failover # +# link will not be tried! Failover settings will also # +# apply to autoconnected servers as well as manually # +# connected ones. # +# # # to u:line a server (give it extra privilages required for running # # services, Q, etc) you must include the tag as shown # # in the example below. You can have as many of these as you like. # @@ -430,6 +448,7 @@ port="7000" allowmask="69.58.44.0/24" autoconnect="300" + failover="hub.other.net" sendpass="outgoing!password" recvpass="incoming!password"> 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 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::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::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 ? "" : 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 { -- cgit v1.2.3