diff options
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/m_spanningtree.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index 0e0f70231..a6db47bf5 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -68,6 +68,7 @@ class TreeServer int UserCount; int OperCount; TreeSocket* Socket; // for directly connected servers this points at the socket object + bool Deleted; public: @@ -78,6 +79,7 @@ class TreeServer ServerDesc = ""; VersionString = ""; UserCount = OperCount = 0; + Deleted = false; } TreeServer(std::string Name, std::string Desc) : ServerName(Name), ServerDesc(Desc) @@ -85,12 +87,14 @@ class TreeServer Parent = NULL; VersionString = ""; UserCount = OperCount = 0; + Deleted = false; } TreeServer(std::string Name, std::string Desc, TreeServer* Above, TreeSocket* Sock) : Parent(Above), ServerName(Name), ServerDesc(Desc), Socket(Sock) { VersionString = ""; UserCount = OperCount = 0; + Deleted = false; } std::string GetName() @@ -145,6 +149,11 @@ class TreeServer } } + void MarkDeleted() + { + this->Deleted = true; + } + void AddChild(TreeServer* Child) { Children.push_back(Child); @@ -162,6 +171,25 @@ class TreeServer } return false; } + + // removes child nodes of this node, and of that node, etc etc + bool Tidy() + { + bool stillchildren = true; + while (stillchildren) + { + stillchildren = false; + for (std::vector<TreeServer*>::iterator a = Children.begin(); a < Children.end(); a++) + { + TreeServer*a = (TreeServer*)*a; + a->Tidy(); + Children.erase(a); + delete a; + stillchildren = true; + break; + } + } + } }; class Link @@ -351,6 +379,40 @@ class TreeSocket : public InspSocket } } + void SquitServer(TreeServer* Current) + { + // recursively squit the servers attached to 'Current' + for (unsigned int q = 0; q < Current->ChildCount(); q++) + { + TreeServer* recursive_server = Current->GetChild(q); + this->SquitServer(recursive_server); + } + // Now we've whacked the kids, whack self + this->MarkDeleted(); + log(DEBUG,"Deleted %s",Current->GetName()); + bool quittingpeople = true; + while (quittingpeople) + { + quittingpeople = false; + for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++) + { + if (!strcasecmp(u->second->server,Current->GetName().c_str())) + { + Srv->QuitUser(u,Current->GetName()+" "+std::string(Srv->GetServerName())); + quittingpeople = true; + break; + } + } + } + } + + void Squit(TreeServer* Current) + { + SquitServer(Current); + Current->Tidy(); + Current->GetParent()->DelChild(Current); + } + bool ForceJoin(std::string source, std::deque<std::string> params) { if (params.size() < 1) @@ -809,6 +871,27 @@ class TreeSocket : public InspSocket virtual void OnClose() { + // Connection closed. + // If the connection is fully up (state CONNECTED) + // then propogate a netsplit to all peers. + std::string quitserver = this->myhost; + if (this->InboundServerName != "") + { + quitserver = this->InboundServerName; + } + TreeServer* s = FindServer(quitserver); + if (s) + { + std::deque<std::string> params; + params.push_back(quitserver); + params.push_back(":Remote host closed the connection"); + DoOneToAllButSender(Srv->GetServerName(),"SQUIT",params,quitserver); + Squit(s); + } + else + { + log(DEBUG,"SQUIT from unknown server %s",quitserver.c_str()); + } } virtual int OnIncomingConnection(int newsock, char* ip) |