summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/snomasks.h7
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp25
-rw-r--r--src/snomasks.cpp12
3 files changed, 44 insertions, 0 deletions
diff --git a/include/snomasks.h b/include/snomasks.h
index 5bd4742c1..d4bd8a22c 100644
--- a/include/snomasks.h
+++ b/include/snomasks.h
@@ -91,6 +91,13 @@ class CoreExport SnomaskManager : public Extensible
*/
bool DisableSnomask(char letter);
+ /** Set the local only message state of a given snomask.
+ * This is used by remote stuff to prevent endless recursion in sending
+ * XXX this is currently a really shit way to do it, as it effectively
+ * bypasses snomask compression!
+ */
+ bool SetLocalOnly(char letter, bool local);
+
/** Write to all users with a given snomask.
* @param letter The snomask letter to write to
* @param text The text to send to the users
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index 8700d57a2..3cd2f8920 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -490,7 +490,32 @@ bool TreeSocket::ProcessLine(std::string &line)
{
if (params.size() >= 2)
{
+ /*
+ * XXX:
+ * The SetLocalOnly stuff here is to work around a bit of a nasty recursion bug.
+ * WriteToSnoMask() sends global snotices out globally, but of course this is a problem
+ * when triggering it from an already global snotice (yay loops).
+ *
+ * The current (horrible) solution I'm implementing here because nobody else seems to
+ * want to look at this except me, sets the snotice local-only temporarily, sends the snotice
+ * and then flushes the snomask.
+ *
+ * This works, but it is total and utter garbage, as it bypasses the snotice compression
+ * totally for this snomask (and may well trigger other snotices to send too early.....)
+ * but at least it won't crash the server.
+ *
+ * Master of hacks, we salute you!
+ * -- w00t
+ */
+
+ // If we get a SNONOTICE, it must have been global... so set it local
+ Instance->SNO->SetLocalOnly(*(params[0].c_str()), true);
+ // send the message
Instance->SNO->WriteToSnoMask(*(params[0].c_str()), "From " + (ServerSource ? ServerSource->GetName().c_str() : prefix) + ": "+ params[1]);
+ // flush the queue
+ Instance->SNO->FlushSnotices();
+ // set it global again
+ Instance->SNO->SetLocalOnly(*(params[0].c_str()), true);
}
return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
}
diff --git a/src/snomasks.cpp b/src/snomasks.cpp
index e6323b50c..2ab473b45 100644
--- a/src/snomasks.cpp
+++ b/src/snomasks.cpp
@@ -40,6 +40,18 @@ void SnomaskManager::FlushSnotices()
}
}
+bool SnomaskManager::SetLocalOnly(char letter, bool local)
+{
+ SnoList::iterator n = SnoMasks.find(letter);
+ if (n != SnoMasks.end())
+ {
+ n->second->LocalOnly = local;
+ return n->second->LocalOnly;
+ }
+
+ throw "snomask not found wtf";
+}
+
bool SnomaskManager::EnableSnomask(char letter, const std::string &type, bool local)
{
if (SnoMasks.find(letter) == SnoMasks.end())