]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/utils.cpp
Add ROUTE_TYPE_MESSAGE and use for PRIVMSG/NOTICE routing
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / utils.cpp
index 729f6d4ee5617bada8bc97bcc41ded37fe3eba78..7b6ea1565abda61914d2fccecc4bf5a91bc9e99f 100644 (file)
@@ -157,11 +157,11 @@ SpanningTreeUtilities::SpanningTreeUtilities(ModuleSpanningTree* C) : Creator(C)
        this->ReadConfiguration(true);
 }
 
-SpanningTreeUtilities::~SpanningTreeUtilities()
+bool SpanningTreeUtilities::cull()
 {
        for (unsigned int i = 0; i < Bindings.size(); i++)
        {
-               delete Bindings[i];
+               Bindings[i]->cull();
        }
 
        while (TreeRoot->ChildCount())
@@ -170,15 +170,24 @@ SpanningTreeUtilities::~SpanningTreeUtilities()
                if (child_server)
                {
                        TreeSocket* sock = child_server->GetSocket();
-                       ServerInstance->SE->DelFd(sock);
                        sock->Close();
                }
        }
-       
-       // This avoids a collision on reload
+
        ServerUser->uuid = TreeRoot->GetID();
+       if (ServerUser->cull())
+               delete ServerUser;
+       return true;
+}
+
+SpanningTreeUtilities::~SpanningTreeUtilities()
+{
+       for (unsigned int i = 0; i < Bindings.size(); i++)
+       {
+               delete Bindings[i];
+       }
+
        delete TreeRoot;
-       delete ServerUser;
 }
 
 void SpanningTreeUtilities::AddThisServer(TreeServer* server, TreeServerList &list)
@@ -212,63 +221,7 @@ void SpanningTreeUtilities::GetListOfServersForChannel(Channel* c, TreeServerLis
 
 bool SpanningTreeUtilities::DoOneToAllButSenderRaw(const std::string &data, const std::string &omit, const std::string &prefix, const irc::string &command, parameterlist &params)
 {
-       char pfx = 0;
        TreeServer* omitroute = this->BestRouteTo(omit);
-       if ((command == "NOTICE") || (command == "PRIVMSG"))
-       {
-               if (params.size() >= 2)
-               {
-                       /* Prefixes */
-                       if (ServerInstance->Modes->FindPrefix(params[0][0]))
-                       {
-                               pfx = params[0][0];
-                               params[0] = params[0].substr(1, params[0].length()-1);
-                       }
-                       if ((*(params[0].c_str()) != '#') && (*(params[0].c_str()) != '$'))
-                       {
-                               // special routing for private messages/notices
-                               User* d = ServerInstance->FindNick(params[0]);
-                               if (d)
-                               {
-                                       parameterlist par;
-                                       par.push_back(params[0]);
-                                       par.push_back(":"+params[1]);
-                                       this->DoOneToOne(prefix,command.c_str(),par,d->server);
-                                       return true;
-                               }
-                       }
-                       else if (*(params[0].c_str()) == '$')
-                       {
-                               parameterlist par;
-                               par.push_back(params[0]);
-                               par.push_back(":"+params[1]);
-                               this->DoOneToAllButSender(prefix,command.c_str(),par,omitroute->GetName());
-                               return true;
-                       }
-                       else
-                       {
-                               Channel* c = ServerInstance->FindChan(params[0]);
-                               User* u = ServerInstance->FindNick(prefix);
-                               if (c)
-                               {
-                                       CUList elist;
-                                       TreeServerList list;
-                                       FOREACH_MOD(I_OnBuildExemptList, OnBuildExemptList((command == "PRIVMSG" ? MSG_PRIVMSG : MSG_NOTICE), c, u, pfx, elist, params[1]));
-                                       GetListOfServersForChannel(c,list,pfx,elist);
-
-                                       for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
-                                       {
-                                               TreeSocket* Sock = i->second->GetSocket();
-                                               if ((Sock) && (i->second->GetName() != omit) && (omitroute != i->second))
-                                               {
-                                                       Sock->WriteLine(data);
-                                               }
-                                       }
-                                       return true;
-                               }
-                       }
-               }
-       }
        unsigned int items =this->TreeRoot->ChildCount();
        for (unsigned int x = 0; x < items; x++)
        {
@@ -374,8 +327,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())
@@ -418,7 +372,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 (...)
@@ -520,55 +474,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;
                        }
 
@@ -577,7 +531,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 (...)
@@ -587,31 +541,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.");
                        }
                }
 
@@ -620,21 +574,24 @@ 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();
-
-               // 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;
+               reference<Autoconnect> A = new Autoconnect;
+               A->Period = Conf->ReadInteger("autoconnect", "period", j, true);
+               A->NextConnectTime = ServerInstance->Time() + A->Period;
+               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);
+               }
 
-               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!");
                }
@@ -645,43 +602,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;