diff options
author | attilamolnar <attilamolnar@hush.com> | 2013-09-02 13:01:41 +0200 |
---|---|---|
committer | attilamolnar <attilamolnar@hush.com> | 2013-09-12 14:44:17 +0200 |
commit | 58d7827bb1bd3d90f38a1c199f6f41ae9f24885c (patch) | |
tree | d2613bd107ac6b00960e1981f184ee4160e5877f | |
parent | 7ba25076818e42b4eac9199477a01101cf57e848 (diff) |
Send ListModeBase modes implicitly on channel sync
Remove Module::ProtoSendMode() and ListModeBase::DoSyncChannel()
-rw-r--r-- | include/listmode.h | 8 | ||||
-rw-r--r-- | include/modules.h | 13 | ||||
-rw-r--r-- | src/listmode.cpp | 22 | ||||
-rw-r--r-- | src/modules.cpp | 1 | ||||
-rw-r--r-- | src/modules/m_autoop.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_banexception.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_chanfilter.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_check.cpp | 47 | ||||
-rw-r--r-- | src/modules/m_exemptchanops.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_inviteexception.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_permchannels.cpp | 63 | ||||
-rw-r--r-- | src/modules/m_spanningtree/commandbuilder.h | 1 | ||||
-rw-r--r-- | src/modules/m_spanningtree/main.cpp | 20 | ||||
-rw-r--r-- | src/modules/m_spanningtree/main.h | 1 | ||||
-rw-r--r-- | src/modules/m_spanningtree/netburst.cpp | 97 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket.h | 4 |
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 ¶meter, 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; |