diff options
| author | 2013-08-19 20:36:41 +0200 | |
|---|---|---|
| committer | 2013-08-28 12:11:33 +0200 | |
| commit | 7432fea968127b606fc029ae462e91d3f30df8a4 (patch) | |
| tree | 396250c0766372c87e83a73d00e2018ed61cc69a /src/modules/m_spanningtree/ftopic.cpp | |
| parent | m_spanningtree Introduce command builders (diff) | |
m_spanningtree Propagate topic changes via FTOPIC in order to prevent desync when two TOPIC messages cross
TOPIC is no longer accepted from servers using the new protocol
Diffstat (limited to 'src/modules/m_spanningtree/ftopic.cpp')
| -rw-r--r-- | src/modules/m_spanningtree/ftopic.cpp | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/src/modules/m_spanningtree/ftopic.cpp b/src/modules/m_spanningtree/ftopic.cpp index 0a4a95f9e..bd15489a2 100644 --- a/src/modules/m_spanningtree/ftopic.cpp +++ b/src/modules/m_spanningtree/ftopic.cpp @@ -44,26 +44,65 @@ CmdResult CommandFTopic::Handle(User* user, std::vector<std::string>& params) if (ts < c->topicset) return CMD_FAILURE; + // The topic text is always the last parameter + const std::string& newtopic = params.back(); + + // If there is a setter in the message use that, otherwise use the message source + const std::string& setter = ((params.size() > 4) ? params[3] : (ServerInstance->Config->FullHostInTopic ? user->GetFullHost() : user->nick)); + /* * If the topics were updated at the exact same second, accept * the remote only when it's "bigger" than ours as defined by * string comparision, so non-empty topics always overridde * empty topics if their timestamps are equal + * + * Similarly, if the topic texts are equal too, keep one topic + * setter and discard the other */ - if ((ts == c->topicset) && (c->topic > params[4])) - return CMD_FAILURE; // Topics were set at the exact same time, keep our topic and setter + if (ts == c->topicset) + { + // Discard if their topic text is "smaller" + if (c->topic > newtopic) + return CMD_FAILURE; - if (c->topic != params[4]) + // If the texts are equal in addition to the timestamps, decide which setter to keep + if ((c->topic == newtopic) && (c->setby >= setter)) + return CMD_FAILURE; + } + + if (c->topic != newtopic) { // Update topic only when it differs from current topic - c->topic.assign(params[4], 0, ServerInstance->Config->Limits.MaxTopic); + c->topic.assign(newtopic, 0, ServerInstance->Config->Limits.MaxTopic); c->WriteChannel(user, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str()); } // Update setter and settime - c->setby.assign(params[3], 0, 127); + c->setby.assign(setter, 0, 128); c->topicset = ts; + FOREACH_MOD(OnPostTopicChange, (user, c, c->topic)); + return CMD_SUCCESS; } +// Used when bursting and in reply to RESYNC, contains topic setter as the 4th parameter +CommandFTopic::Builder::Builder(Channel* chan) + : CmdBuilder("FTOPIC") +{ + push(chan->name); + push_int(chan->age); + push_int(chan->topicset); + push(chan->setby); + push_last(chan->topic); +} + +// Used when changing the topic, the setter is the message source +CommandFTopic::Builder::Builder(User* user, Channel* chan) + : CmdBuilder(user, "FTOPIC") +{ + push(chan->name); + push_int(chan->age); + push_int(chan->topicset); + push_last(chan->topic); +} |
