summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/m_spanningtree/main.cpp2
-rw-r--r--src/modules/m_spanningtree/override_squit.cpp5
-rw-r--r--src/modules/m_spanningtree/rsquit.cpp4
-rw-r--r--src/modules/m_spanningtree/treeserver.cpp52
-rw-r--r--src/modules/m_spanningtree/treeserver.h18
-rw-r--r--src/modules/m_spanningtree/treesocket.h18
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp95
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp2
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 &params);
- /** 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());