summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorattilamolnar <attilamolnar@hush.com>2013-09-02 13:01:41 +0200
committerattilamolnar <attilamolnar@hush.com>2013-09-12 14:44:17 +0200
commit58d7827bb1bd3d90f38a1c199f6f41ae9f24885c (patch)
treed2613bd107ac6b00960e1981f184ee4160e5877f
parent7ba25076818e42b4eac9199477a01101cf57e848 (diff)
Send ListModeBase modes implicitly on channel sync
Remove Module::ProtoSendMode() and ListModeBase::DoSyncChannel()
-rw-r--r--include/listmode.h8
-rw-r--r--include/modules.h13
-rw-r--r--src/listmode.cpp22
-rw-r--r--src/modules.cpp1
-rw-r--r--src/modules/m_autoop.cpp5
-rw-r--r--src/modules/m_banexception.cpp5
-rw-r--r--src/modules/m_chanfilter.cpp5
-rw-r--r--src/modules/m_check.cpp47
-rw-r--r--src/modules/m_exemptchanops.cpp5
-rw-r--r--src/modules/m_inviteexception.cpp5
-rw-r--r--src/modules/m_permchannels.cpp63
-rw-r--r--src/modules/m_spanningtree/commandbuilder.h1
-rw-r--r--src/modules/m_spanningtree/main.cpp20
-rw-r--r--src/modules/m_spanningtree/main.h1
-rw-r--r--src/modules/m_spanningtree/netburst.cpp97
-rw-r--r--src/modules/m_spanningtree/treesocket.h4
16 files changed, 148 insertions, 154 deletions
diff --git a/include/listmode.h b/include/listmode.h
index e6ca88d4c..75385588b 100644
--- a/include/listmode.h
+++ b/include/listmode.h
@@ -162,14 +162,6 @@ class CoreExport ListModeBase : public ModeHandler
*/
virtual ModeAction OnModeChange(User* source, User*, Channel* channel, std::string &parameter, bool adding);
- /** Syncronize channel item list with another server.
- * See modules.h
- * @param chan Channel to syncronize
- * @param proto Protocol module pointer
- * @param opaque Opaque connection handle
- */
- virtual void DoSyncChannel(Channel* chan, Module* proto, void* opaque);
-
/** Validate parameters.
* Overridden by implementing module.
* @param user Source user adding the parameter
diff --git a/include/modules.h b/include/modules.h
index d7b46ad48..e04ee01ff 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -670,19 +670,6 @@ class CoreExport Module : public classbase, public usecountbase
virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata);
/** Implemented by modules which provide the ability to link servers.
- * These modules will implement this method, which allows transparent sending of servermodes
- * down the network link as a broadcast, without a module calling it having to know the format
- * of the MODE command before the actual mode string.
- *
- * @param opaque An opaque pointer set by the protocol module, should not be modified!
- * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL
- * @param target The Channel* or User* that modes should be sent for
- * @param modeline The modes and parameters to be sent
- * @param translate The translation types of the mode parameters
- */
- virtual void ProtoSendMode(void* opaque, TargetTypeFlags target_type, void* target, const std::vector<std::string> &modeline, const std::vector<TranslateType> &translate);
-
- /** Implemented by modules which provide the ability to link servers.
* These modules will implement this method, which allows metadata (extra data added to
* user and channel records using class Extensible, Extensible::Extend, etc) to be sent
* to other servers on a netburst and decoded at the other end by the same module on a
diff --git a/src/listmode.cpp b/src/listmode.cpp
index 4ab15b2dc..3c9183ff7 100644
--- a/src/listmode.cpp
+++ b/src/listmode.cpp
@@ -204,28 +204,6 @@ ModeAction ListModeBase::OnModeChange(User* source, User*, Channel* channel, std
}
}
-void ListModeBase::DoSyncChannel(Channel* chan, Module* proto, void* opaque)
-{
- ChanData* cd = extItem.get(chan);
- if (!cd)
- return;
-
- irc::modestacker modestack(true);
- std::vector<std::string> stackresult;
- std::vector<TranslateType> types;
- types.push_back(TR_TEXT);
-
- for (ModeList::iterator it = cd->list.begin(); it != cd->list.end(); it++)
- modestack.Push(mode, it->mask);
-
- while (modestack.GetStackedLine(stackresult))
- {
- types.assign(stackresult.size(), this->GetTranslateType());
- proto->ProtoSendMode(opaque, TYPE_CHANNEL, chan, stackresult, types);
- stackresult.clear();
- }
-}
-
bool ListModeBase::ValidateParam(User*, Channel*, std::string&)
{
return true;
diff --git a/src/modules.cpp b/src/modules.cpp
index 8255049b1..388a57905 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -137,7 +137,6 @@ void Module::OnGetServerDescription(const std::string&, std::string&) { DetachE
void Module::OnSyncUser(User*, Module*, void*) { DetachEvent(I_OnSyncUser); }
void Module::OnSyncChannel(Channel*, Module*, void*) { DetachEvent(I_OnSyncChannel); }
void Module::OnSyncNetwork(Module*, void*) { DetachEvent(I_OnSyncNetwork); }
-void Module::ProtoSendMode(void*, TargetTypeFlags, void*, const std::vector<std::string>&, const std::vector<TranslateType>&) { }
void Module::OnDecodeMetaData(Extensible*, const std::string&, const std::string&) { DetachEvent(I_OnDecodeMetaData); }
void Module::ProtoSendMetaData(void*, Extensible*, const std::string&, const std::string&) { }
void Module::OnChangeHost(User*, const std::string&) { DetachEvent(I_OnChangeHost); }
diff --git a/src/modules/m_autoop.cpp b/src/modules/m_autoop.cpp
index a1b72714b..2ef9fe59e 100644
--- a/src/modules/m_autoop.cpp
+++ b/src/modules/m_autoop.cpp
@@ -118,11 +118,6 @@ class ModuleAutoOp : public Module
}
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
- {
- mh.DoSyncChannel(chan, proto, opaque);
- }
-
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
mh.DoRehash();
diff --git a/src/modules/m_banexception.cpp b/src/modules/m_banexception.cpp
index 62742a527..b10ed3604 100644
--- a/src/modules/m_banexception.cpp
+++ b/src/modules/m_banexception.cpp
@@ -105,11 +105,6 @@ class ModuleBanException : public Module
return MOD_RES_PASSTHRU;
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
- {
- be.DoSyncChannel(chan, proto, opaque);
- }
-
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
be.DoRehash();
diff --git a/src/modules/m_chanfilter.cpp b/src/modules/m_chanfilter.cpp
index dc5718bde..1372a32c9 100644
--- a/src/modules/m_chanfilter.cpp
+++ b/src/modules/m_chanfilter.cpp
@@ -117,11 +117,6 @@ class ModuleChanFilter : public Module
return MOD_RES_PASSTHRU;
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
- {
- cf.DoSyncChannel(chan, proto, opaque);
- }
-
Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel-specific censor lists (like mode +G but varies from channel to channel)", VF_VENDOR);
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp
index cf99e6404..5e154feea 100644
--- a/src/modules/m_check.cpp
+++ b/src/modules/m_check.cpp
@@ -27,7 +27,6 @@
*/
class CommandCheck : public Command
{
- ChanModeReference ban;
UserModeReference snomaskmode;
std::string GetSnomasks(User* user)
@@ -41,10 +40,30 @@ class CommandCheck : public Command
return ret;
}
+ static void dumpListMode(User* user, const std::string& checkstr, const ListModeBase::ModeList* list)
+ {
+ if (!list)
+ return;
+
+ std::string buf = checkstr + " modelist";
+ const std::string::size_type headlen = buf.length();
+ const size_t maxline = ServerInstance->Config->Limits.MaxLine;
+ for (ListModeBase::ModeList::const_iterator i = list->begin(); i != list->end(); ++i)
+ {
+ if (buf.size() + i->mask.size() + 1 > maxline)
+ {
+ user->SendText(buf);
+ buf.erase(headlen);
+ }
+ buf.append(" ").append(i->mask);
+ }
+ if (buf.length() > headlen)
+ user->SendText(buf);
+ }
+
public:
CommandCheck(Module* parent)
: Command(parent,"CHECK", 1)
- , ban(parent, "ban")
, snomaskmode(parent, "snomask")
{
flags_needed = 'o'; syntax = "<nickname>|<ip>|<hostmask>|<channel> <server>";
@@ -215,12 +234,10 @@ class CommandCheck : public Command
i->first->ident.c_str(), i->first->dhost.c_str(), i->first->fullname.c_str());
}
- // We know that the mode handler for bans is in the core and is derived from ListModeBase
- ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
- banlm->DoSyncChannel(targchan, creator, user);
+ const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes();
+ for (ModeParser::ListModeList::const_iterator i = listmodes.begin(); i != listmodes.end(); ++i)
+ dumpListMode(user, checkstr, (*i)->GetList(targchan));
- // Show other listmodes as well
- FOREACH_MOD(OnSyncChannel, (targchan,creator,user));
dumpExt(user, checkstr, targchan);
}
else
@@ -268,22 +285,6 @@ class ModuleCheck : public Module
{
}
- void ProtoSendMode(void* uv, TargetTypeFlags, void*, const std::vector<std::string>& result, const std::vector<TranslateType>&)
- {
- User* user = (User*)uv;
- std::string checkstr(":");
- checkstr.append(ServerInstance->Config->ServerName);
- checkstr.append(" 304 ");
- checkstr.append(user->nick);
- checkstr.append(" :CHECK modelist");
- for(unsigned int i=0; i < result.size(); i++)
- {
- checkstr.append(" ");
- checkstr.append(result[i]);
- }
- user->SendText(checkstr);
- }
-
Version GetVersion() CXX11_OVERRIDE
{
return Version("CHECK command, view user, channel, IP address or hostname information", VF_VENDOR|VF_OPTCOMMON);
diff --git a/src/modules/m_exemptchanops.cpp b/src/modules/m_exemptchanops.cpp
index a733fa475..8a18c46c6 100644
--- a/src/modules/m_exemptchanops.cpp
+++ b/src/modules/m_exemptchanops.cpp
@@ -134,11 +134,6 @@ class ModuleExemptChanOps : public Module
{
eh.ec.DoRehash();
}
-
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
- {
- eh.ec.DoSyncChannel(chan, proto, opaque);
- }
};
MODULE_INIT(ModuleExemptChanOps)
diff --git a/src/modules/m_inviteexception.cpp b/src/modules/m_inviteexception.cpp
index 08322f9cf..6229e1fa2 100644
--- a/src/modules/m_inviteexception.cpp
+++ b/src/modules/m_inviteexception.cpp
@@ -80,11 +80,6 @@ public:
return MOD_RES_PASSTHRU;
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
- {
- ie.DoSyncChannel(chan, proto, opaque);
- }
-
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
invite_bypass_key = ServerInstance->Config->ConfValue("inviteexception")->getBool("bypasskey", true);
diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp
index 2190a5206..a0b3284e3 100644
--- a/src/modules/m_permchannels.cpp
+++ b/src/modules/m_permchannels.cpp
@@ -23,12 +23,6 @@
#include <fstream>
-struct ListModeData
-{
- std::string modes;
- std::string params;
-};
-
/** Handles the +P channel mode
*/
class PermChannel : public ModeHandler
@@ -89,33 +83,45 @@ static bool WriteDatabase(PermChannel& permchanmode, Module* mod, bool save_list
std::string chanmodes = chan->ChanModes(true);
if (save_listmodes)
{
- ListModeData lm;
+ std::string modes;
+ std::string params;
- // Bans are managed by the core, so we have to process them separately
- static_cast<ListModeBase*>(*ban)->DoSyncChannel(chan, mod, &lm);
+ const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes();
+ for (ModeParser::ListModeList::const_iterator j = listmodes.begin(); j != listmodes.end(); ++j)
+ {
+ ListModeBase* lm = *j;
+ ListModeBase::ModeList* list = lm->GetList(chan);
+ if (!list || list->empty())
+ continue;
- // All other listmodes are managed by modules, so we need to ask them (call their
- // OnSyncChannel() handler) to give our ProtoSendMode() a list of modes that are
- // set on the channel. The ListModeData struct is passed as an opaque pointer
- // that will be passed back to us by the module handling the mode.
- FOREACH_MOD(OnSyncChannel, (chan, mod, &lm));
+ size_t n = 0;
+ // Append the parameters
+ for (ListModeBase::ModeList::const_iterator k = list->begin(); k != list->end(); ++k, n++)
+ {
+ params += k->mask;
+ params += ' ';
+ }
+
+ // Append the mode letters (for example "IIII", "gg")
+ modes.append(n, lm->GetModeChar());
+ }
- if (!lm.modes.empty())
+ if (!params.empty())
{
// Remove the last space
- lm.params.erase(lm.params.end()-1);
+ params.erase(params.end()-1);
// If there is at least a space in chanmodes (that is, a non-listmode has a parameter)
// insert the listmode mode letters before the space. Otherwise just append them.
std::string::size_type p = chanmodes.find(' ');
if (p == std::string::npos)
- chanmodes += lm.modes;
+ chanmodes += modes;
else
- chanmodes.insert(p, lm.modes);
+ chanmodes.insert(p, modes);
// Append the listmode parameters (the masks themselves)
chanmodes += ' ';
- chanmodes += lm.params;
+ chanmodes += params;
}
}
@@ -320,25 +326,6 @@ public:
}
}
- void ProtoSendMode(void* opaque, TargetTypeFlags type, void* target, const std::vector<std::string>& modes, const std::vector<TranslateType>& translate)
- {
- // We never pass an empty modelist but better be sure
- if (modes.empty())
- return;
-
- ListModeData* lm = static_cast<ListModeData*>(opaque);
-
- // Append the mode letters without the trailing '+' (for example "IIII", "gg")
- lm->modes.append(modes[0].begin()+1, modes[0].end());
-
- // Append the parameters
- for (std::vector<std::string>::const_iterator i = modes.begin()+1; i != modes.end(); ++i)
- {
- lm->params += *i;
- lm->params += ' ';
- }
- }
-
Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for channel mode +P to provide permanent channels",VF_VENDOR);
diff --git a/src/modules/m_spanningtree/commandbuilder.h b/src/modules/m_spanningtree/commandbuilder.h
index 597b22751..aa4778fa9 100644
--- a/src/modules/m_spanningtree/commandbuilder.h
+++ b/src/modules/m_spanningtree/commandbuilder.h
@@ -25,6 +25,7 @@ class TreeServer;
class CmdBuilder
{
+ protected:
std::string content;
public:
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index f264f9a7a..6e992c02d 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -718,26 +718,6 @@ ModResult ModuleSpanningTree::OnSetAway(User* user, const std::string &awaymsg)
return MOD_RES_PASSTHRU;
}
-void ModuleSpanningTree::ProtoSendMode(void* opaque, TargetTypeFlags target_type, void* target, const parameterlist &modeline, const std::vector<TranslateType> &translate)
-{
- TreeSocket* s = (TreeSocket*)opaque;
- std::string output_text = CommandParser::TranslateUIDs(translate, modeline);
-
- if (target)
- {
- if (target_type == TYPE_USER)
- {
- User* u = (User*)target;
- s->WriteLine(":"+ServerInstance->Config->GetSID()+" MODE "+u->uuid+" "+output_text);
- }
- else if (target_type == TYPE_CHANNEL)
- {
- Channel* c = (Channel*)target;
- s->WriteLine(":"+ServerInstance->Config->GetSID()+" FMODE "+c->name+" "+ConvToStr(c->age)+" "+output_text);
- }
- }
-}
-
void ModuleSpanningTree::ProtoSendMetaData(void* opaque, Extensible* target, const std::string &extname, const std::string &extdata)
{
TreeSocket* s = static_cast<TreeSocket*>(opaque);
diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h
index 8a13c7814..737b7d576 100644
--- a/src/modules/m_spanningtree/main.h
+++ b/src/modules/m_spanningtree/main.h
@@ -158,7 +158,6 @@ class ModuleSpanningTree : public Module
void OnDelLine(User *u, XLine *x) CXX11_OVERRIDE;
ModResult OnStats(char statschar, User* user, string_list &results) CXX11_OVERRIDE;
ModResult OnSetAway(User* user, const std::string &awaymsg) CXX11_OVERRIDE;
- void ProtoSendMode(void* opaque, TargetTypeFlags target_type, void* target, const std::vector<std::string> &modeline, const std::vector<TranslateType> &translate);
void ProtoSendMetaData(void* opaque, Extensible* target, const std::string &extname, const std::string &extdata);
void OnLoadModule(Module* mod) CXX11_OVERRIDE;
void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp
index d4669442a..9ca5b04d4 100644
--- a/src/modules/m_spanningtree/netburst.cpp
+++ b/src/modules/m_spanningtree/netburst.cpp
@@ -28,6 +28,67 @@
#include "main.h"
#include "commands.h"
+/**
+ * Creates FMODE messages, used only when syncing channels
+ */
+class FModeBuilder : public CmdBuilder
+{
+ static const size_t maxline = 480;
+ std::string params;
+ unsigned int modes;
+ std::string::size_type startpos;
+
+ public:
+ FModeBuilder(Channel* chan)
+ : CmdBuilder("FMODE"), modes(0)
+ {
+ push(chan->name).push_int(chan->age).push_raw(" +");
+ startpos = str().size();
+ }
+
+ /** Add a mode to the message
+ */
+ void push_mode(const char modeletter, const std::string& mask)
+ {
+ push_raw(modeletter);
+ params.push_back(' ');
+ params.append(mask);
+ modes++;
+ }
+
+ /** Remove all modes from the message
+ */
+ void clear()
+ {
+ content.erase(startpos);
+ params.clear();
+ modes = 0;
+ }
+
+ /** Prepare the message for sending, next mode can only be added after clear()
+ */
+ const std::string& finalize()
+ {
+ return push_raw(params);
+ }
+
+ /** Returns true if the given mask can be added to the message, false if the message
+ * has no room for the mask
+ */
+ bool has_room(const std::string& mask) const
+ {
+ return ((str().size() + params.size() + mask.size() + 2 <= maxline) &&
+ (modes < ServerInstance->Config->Limits.MaxModes));
+ }
+
+ /** Returns true if this message is empty (has no modes)
+ */
+ bool empty() const
+ {
+ return (modes == 0);
+ }
+};
+
/** This function is called when we want to send a netburst to a local
* server. There is a set order we must do this, because for example
* users require their servers to exist, and channels require their
@@ -107,9 +168,6 @@ void TreeSocket::SendFJoins(Channel* c)
line.append(modestr).append(1, ',').append(i->first->uuid).push_back(' ');
}
this->WriteLine(line);
-
- ChanModeReference ban(NULL, "ban");
- static_cast<ListModeBase*>(*ban)->DoSyncChannel(c, Utils->Creator, this);
}
/** Send all XLines we know about */
@@ -139,6 +197,37 @@ void TreeSocket::SendXLines()
}
}
+void TreeSocket::SendListModes(Channel* chan)
+{
+ FModeBuilder fmode(chan);
+ const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes();
+ for (ModeParser::ListModeList::const_iterator i = listmodes.begin(); i != listmodes.end(); ++i)
+ {
+ ListModeBase* mh = *i;
+ ListModeBase::ModeList* list = mh->GetList(chan);
+ if (!list)
+ continue;
+
+ // Add all items on the list to the FMODE, send it whenever it becomes too long
+ const char modeletter = mh->GetModeChar();
+ for (ListModeBase::ModeList::const_iterator j = list->begin(); j != list->end(); ++j)
+ {
+ const std::string& mask = j->mask;
+ if (!fmode.has_room(mask))
+ {
+ // No room for this mask, send the current line as-is then add the mask to a
+ // new, empty FMODE message
+ this->WriteLine(fmode.finalize());
+ fmode.clear();
+ }
+ fmode.push_mode(modeletter, mask);
+ }
+ }
+
+ if (!fmode.empty())
+ this->WriteLine(fmode.finalize());
+}
+
/** Send channel topic, modes and metadata */
void TreeSocket::SyncChannel(Channel* chan)
{
@@ -149,6 +238,8 @@ void TreeSocket::SyncChannel(Channel* chan)
if (chan->topicset != 0)
this->WriteLine(CommandFTopic::Builder(chan));
+ SendListModes(chan);
+
for (Extensible::ExtensibleStore::const_iterator i = chan->GetExtList().begin(); i != chan->GetExtList().end(); i++)
{
ExtensionItem* item = i->first;
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index 6d79711cc..8c87c4df6 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -102,6 +102,10 @@ class TreeSocket : public BufferedSocket
*/
bool CheckDuplicate(const std::string& servername, const std::string& sid);
+ /** Send all ListModeBase modes set on the channel
+ */
+ void SendListModes(Channel* chan);
+
public:
const time_t age;