diff options
author | Attila Molnar <attilamolnar@hush.com> | 2014-07-28 14:30:14 +0200 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2014-07-28 14:30:14 +0200 |
commit | 5214968e7e0e0d43e137535ac1a9369c222d79f0 (patch) | |
tree | ff06c606ce82c73fd75587af9110b5954a260d3f /src | |
parent | 91ba5c22664cae39d53f52af663a154286455e01 (diff) |
m_spanningtree Move squit logic into TreeServer from TreeSocket
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/m_spanningtree/main.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_spanningtree/override_squit.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_spanningtree/rsquit.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treeserver.cpp | 52 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treeserver.h | 18 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket.h | 18 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket1.cpp | 95 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket2.cpp | 2 |
8 files changed, 84 insertions, 112 deletions
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index c135cd134..e3814a885 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -701,7 +701,7 @@ restart: { sock->SendError("SSL module unloaded"); sock->Close(); - // XXX: The list we're iterating is modified by TreeSocket::Squit() which is called by Close() + // XXX: The list we're iterating is modified by TreeServer::SQuit() which is called by Close() goto restart; } } diff --git a/src/modules/m_spanningtree/override_squit.cpp b/src/modules/m_spanningtree/override_squit.cpp index 84cb01f50..9cec527d3 100644 --- a/src/modules/m_spanningtree/override_squit.cpp +++ b/src/modules/m_spanningtree/override_squit.cpp @@ -36,13 +36,10 @@ ModResult ModuleSpanningTree::HandleSquit(const std::vector<std::string>& parame return MOD_RES_DENY; } - TreeSocket* sock = s->GetSocket(); - if (s->IsLocal()) { ServerInstance->SNO->WriteToSnoMask('l',"SQUIT: Server \002%s\002 removed from network by %s",parameters[0].c_str(),user->nick.c_str()); - sock->Squit(s,"Server quit by " + user->GetFullRealHost()); - sock->Close(); + s->SQuit("Server quit by " + user->GetFullRealHost()); } else { diff --git a/src/modules/m_spanningtree/rsquit.cpp b/src/modules/m_spanningtree/rsquit.cpp index 988918c3f..45413c33f 100644 --- a/src/modules/m_spanningtree/rsquit.cpp +++ b/src/modules/m_spanningtree/rsquit.cpp @@ -52,11 +52,9 @@ CmdResult CommandRSQuit::Handle (const std::vector<std::string>& parameters, Use if (server_target->IsLocal()) { // We have been asked to remove server_target. - TreeSocket* sock = server_target->GetSocket(); const char* reason = parameters.size() == 2 ? parameters[1].c_str() : "No reason"; ServerInstance->SNO->WriteToSnoMask('l',"RSQUIT: Server \002%s\002 removed from network by %s (%s)", parameters[0].c_str(), user->nick.c_str(), reason); - sock->Squit(server_target, "Server quit by " + user->GetFullRealHost() + " (" + reason + ")"); - sock->Close(); + server_target->SQuit("Server quit by " + user->GetFullRealHost() + " (" + reason + ")"); } return CMD_SUCCESS; diff --git a/src/modules/m_spanningtree/treeserver.cpp b/src/modules/m_spanningtree/treeserver.cpp index f4c7b511e..f493f6d20 100644 --- a/src/modules/m_spanningtree/treeserver.cpp +++ b/src/modules/m_spanningtree/treeserver.cpp @@ -163,6 +163,58 @@ void TreeServer::FinishBurst() FinishBurstInternal(); } +void TreeServer::SQuitChild(TreeServer* server, const std::string& reason) +{ + DelServerEvent(Utils->Creator, server->GetName()); + DelChild(server); + + if (IsRoot()) + { + // Server split from us, generate a SQUIT message and broadcast it + ServerInstance->SNO->WriteGlobalSno('l', "Server \002" + server->GetName() + "\002 split: " + reason); + CmdBuilder("SQUIT").push(server->GetID()).push_last(reason).Broadcast(); + } + else + { + ServerInstance->SNO->WriteToSnoMask('L', "Server \002" + server->GetName() + "\002 split from server \002" + GetName() + "\002 with reason: " + reason); + } + + int num_lost_servers = 0; + int num_lost_users = 0; + const std::string quitreason = GetName() + " " + server->GetName(); + + ModuleSpanningTree* st = Utils->Creator; + st->SplitInProgress = true; + server->SQuitInternal(quitreason, num_lost_servers, num_lost_users); + st->SplitInProgress = false; + + ServerInstance->SNO->WriteToSnoMask(IsRoot() ? 'l' : 'L', "Netsplit complete, lost \002%d\002 user%s on \002%d\002 server%s.", + num_lost_users, num_lost_users != 1 ? "s" : "", num_lost_servers, num_lost_servers != 1 ? "s" : ""); + + server->Tidy(); + + // No-op if the socket is already closed (i.e. it called us) + if (server->IsLocal()) + server->GetSocket()->Close(); + + server->cull(); + delete server; +} + +void TreeServer::SQuitInternal(const std::string& reason, int& num_lost_servers, int& num_lost_users) +{ + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Server %s lost in split", GetName().c_str()); + + for (ChildServers::const_iterator i = Children.begin(); i != Children.end(); ++i) + { + TreeServer* server = *i; + server->SQuitInternal(reason, num_lost_servers, num_lost_users); + } + + num_lost_servers++; + num_lost_users += QuitUsers(reason); +} + int TreeServer::QuitUsers(const std::string &reason) { std::string publicreason = ServerInstance->Config->HideSplits ? "*.net *.split" : reason; diff --git a/src/modules/m_spanningtree/treeserver.h b/src/modules/m_spanningtree/treeserver.h index 3f1f0755d..2e6c47bf4 100644 --- a/src/modules/m_spanningtree/treeserver.h +++ b/src/modules/m_spanningtree/treeserver.h @@ -65,6 +65,10 @@ class TreeServer : public Server */ void AddHashEntry(); + /** Used by SQuit logic to recursively remove servers + */ + void SQuitInternal(const std::string& reason, int& num_lost_servers, int& num_lost_users); + public: typedef std::vector<TreeServer*> ChildServers; FakeUser* const ServerUser; /* User representing this server */ @@ -87,6 +91,20 @@ class TreeServer : public Server */ TreeServer(const std::string& Name, const std::string& Desc, const std::string& id, TreeServer* Above, TreeSocket* Sock, bool Hide); + /** SQuit a server connected to this server, removing the given server and all servers behind it + * @param server Server to squit, must be directly below this server + * @param reason Reason for quitting the server, sent to opers and other servers + */ + void SQuitChild(TreeServer* server, const std::string& reason); + + /** SQuit this server, removing this server and all servers behind it + * @param reason Reason for quitting the server, sent to opers and other servers + */ + void SQuit(const std::string& reason) + { + GetParent()->SQuitChild(this, reason); + } + int QuitUsers(const std::string &reason); /** Get route. diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 274337d3f..a775d7c24 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -250,20 +250,6 @@ class TreeSocket : public BufferedSocket bool Capab(const parameterlist ¶ms); - /** This function forces this server to quit, removing this server - * and any users on it (and servers and users below that, etc etc). - * It's very slow and pretty clunky, but luckily unless your network - * is having a REAL bad hair day, this function shouldnt be called - * too many times a month ;-) - */ - void SquitServer(std::string &from, TreeServer* Current, int& num_lost_servers, int& num_lost_users); - - /** This is a wrapper function for SquitServer above, which - * does some validation first and passes on the SQUIT to all - * other remaining servers. - */ - void Squit(TreeServer* Current, const std::string &reason); - /** Send one or more FJOINs for a channel of users. * If the length of a single line is more than 480-NICKMAX * in length, it is split over multiple lines. @@ -320,10 +306,6 @@ class TreeSocket : public BufferedSocket */ void Close(); - /** Returns true if this server was introduced to the rest of the network - */ - bool Introduced(); - /** Fixes messages coming from old servers so the new command handlers understand them */ bool PreProcessOldProtocolMessage(User*& who, std::string& cmd, std::vector<std::string>& params); diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 5deef8394..27d7b1a57 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -138,82 +138,6 @@ void TreeSocket::SendError(const std::string &errormessage) SetError(errormessage); } -/** This function forces this server to quit, removing this server - * and any users on it (and servers and users below that, etc etc). - * It's very slow and pretty clunky, but luckily unless your network - * is having a REAL bad hair day, this function shouldnt be called - * too many times a month ;-) - */ -void TreeSocket::SquitServer(std::string &from, TreeServer* Current, int& num_lost_servers, int& num_lost_users) -{ - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "SquitServer for %s from %s", Current->GetName().c_str(), from.c_str()); - /* recursively squit the servers attached to 'Current'. - * We're going backwards so we don't remove users - * while we still need them ;) - */ - const TreeServer::ChildServers& children = Current->GetChildren(); - for (TreeServer::ChildServers::const_iterator i = children.begin(); i != children.end(); ++i) - { - TreeServer* recursive_server = *i; - this->SquitServer(from,recursive_server, num_lost_servers, num_lost_users); - } - /* Now we've whacked the kids, whack self */ - num_lost_servers++; - num_lost_users += Current->QuitUsers(from); -} - -/** This is a wrapper function for SquitServer above, which - * does some validation first and passes on the SQUIT to all - * other remaining servers. - */ -void TreeSocket::Squit(TreeServer* Current, const std::string &reason) -{ - bool LocalSquit = false; - - if (!Current->IsRoot()) - { - DelServerEvent(Utils->Creator, Current->GetName()); - - if (Current->IsLocal()) - { - ServerInstance->SNO->WriteGlobalSno('l', "Server \002"+Current->GetName()+"\002 split: "+reason); - LocalSquit = true; - if (Current->GetSocket()->Introduced()) - { - CmdBuilder params("SQUIT"); - params.push_back(Current->GetID()); - params.push_last(reason); - params.Broadcast(); - } - } - else - { - ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+Current->GetName()+"\002 split from server \002"+Current->GetParent()->GetName()+"\002 with reason: "+reason); - } - int num_lost_servers = 0; - int num_lost_users = 0; - std::string from = Current->GetParent()->GetName()+" "+Current->GetName(); - - ModuleSpanningTree* st = Utils->Creator; - st->SplitInProgress = true; - SquitServer(from, Current, num_lost_servers, num_lost_users); - st->SplitInProgress = false; - - ServerInstance->SNO->WriteToSnoMask(LocalSquit ? 'l' : 'L', "Netsplit complete, lost \002%d\002 user%s on \002%d\002 server%s.", - num_lost_users, num_lost_users != 1 ? "s" : "", num_lost_servers, num_lost_servers != 1 ? "s" : ""); - Current->Tidy(); - Current->GetParent()->DelChild(Current); - Current->cull(); - const bool ismyroot = (Current == MyRoot); - delete Current; - if (ismyroot) - { - MyRoot = NULL; - Close(); - } - } -} - CmdResult CommandSQuit::HandleServer(TreeServer* server, std::vector<std::string>& params) { TreeServer* quitting = Utils->FindServer(params[0]); @@ -223,15 +147,21 @@ CmdResult CommandSQuit::HandleServer(TreeServer* server, std::vector<std::string return CMD_FAILURE; } - TreeSocket* sock = server->GetSocket(); - sock->Squit(quitting, params[1]); + CmdResult ret = CMD_SUCCESS; + if (quitting == server) + { + ret = CMD_FAILURE; + server = server->GetParent(); + } + + server->SQuitChild(quitting, params[1]); // XXX: Return CMD_FAILURE when servers SQUIT themselves (i.e. :00S SQUIT 00S :Shutting down) // to avoid RouteCommand() being called. RouteCommand() requires a valid command source but we // do not have one because the server user is deleted when its TreeServer is destructed. - // We generate a SQUIT in TreeSocket::Squit(), with our sid as the source and send it to the + // The squit logic generates a SQUIT message with our sid as the source and sends it to the // remaining servers. - return ((quitting == server) ? CMD_FAILURE : CMD_SUCCESS); + return ret; } /** This function is called when we receive data from a remote @@ -270,8 +200,3 @@ void TreeSocket::OnDataReady() SendError("RecvQ overrun (line too long)"); Utils->Creator->loopCall = false; } - -bool TreeSocket::Introduced() -{ - return (capab == NULL); -} diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 574dda09d..7574be90a 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -355,7 +355,7 @@ void TreeSocket::Close() // If the connection is fully up (state CONNECTED) // then propogate a netsplit to all peers. if (MyRoot) - Squit(MyRoot,getError()); + MyRoot->SQuit(getError()); ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\2%s\2' failed.",linkID.c_str()); |