summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clientprotocol.h2
-rw-r--r--src/modules/m_spanningtree/commandbuilder.h24
-rw-r--r--src/modules/m_spanningtree/main.cpp5
-rw-r--r--src/modules/m_spanningtree/main.h3
-rw-r--r--src/modules/m_spanningtree/postcommand.cpp3
-rw-r--r--src/modules/m_spanningtree/protocolinterface.cpp3
-rw-r--r--src/modules/m_spanningtree/treesocket.h8
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp85
-rw-r--r--src/modules/m_spanningtree/utils.cpp3
-rw-r--r--src/modules/m_spanningtree/utils.h2
10 files changed, 108 insertions, 30 deletions
diff --git a/include/clientprotocol.h b/include/clientprotocol.h
index 260e463eb..10b70e80b 100644
--- a/include/clientprotocol.h
+++ b/include/clientprotocol.h
@@ -549,7 +549,7 @@ class ClientProtocol::MessageTagProvider : public Events::ModuleEventListener
* MOD_RES_PASSTHRU to make no decision. If no hooks accept a tag, the tag is rejected.
* The default implementation returns MOD_RES_PASSTHRU.
*/
- virtual ModResult OnClientProtocolProcessTag(LocalUser* user, const std::string& tagname, std::string& tagvalue)
+ virtual ModResult OnClientProtocolProcessTag(User* user, const std::string& tagname, std::string& tagvalue)
{
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_spanningtree/commandbuilder.h b/src/modules/m_spanningtree/commandbuilder.h
index 59de84052..4bbb60e47 100644
--- a/src/modules/m_spanningtree/commandbuilder.h
+++ b/src/modules/m_spanningtree/commandbuilder.h
@@ -119,6 +119,30 @@ class CmdBuilder
return *this;
}
+ CmdBuilder& push_tags(const ClientProtocol::TagMap& tags)
+ {
+ if (!tags.empty())
+ {
+ char separator = '@';
+ std::string taglist;
+ for (ClientProtocol::TagMap::const_iterator iter = tags.begin(); iter != tags.end(); ++iter)
+ {
+ taglist.push_back(separator);
+ separator = ';';
+
+ taglist.append(iter->first);
+ if (!iter->second.value.empty())
+ {
+ taglist.push_back('=');
+ taglist.append(iter->second.value);
+ }
+ }
+ taglist.push_back(' ');
+ content.insert(0, taglist);
+ }
+ return *this;
+ }
+
template<typename T>
CmdBuilder& insert(const T& cont)
{
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index 2a4e927a4..985762872 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -46,6 +46,7 @@ ModuleSpanningTree::ModuleSpanningTree()
, currmembid(0)
, eventprov(this, "event/server")
, DNS(this, "DNS")
+ , tagevprov(this, "event/messagetag")
, loopCall(false)
{
}
@@ -410,6 +411,7 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
if (!IS_LOCAL(d))
{
CmdBuilder params(user, message_type);
+ params.push_tags(details.tags_out);
params.push_back(d->uuid);
params.push_last(details.text);
params.Unicast(d);
@@ -417,12 +419,13 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
}
else if (target.type == MessageTarget::TYPE_CHANNEL)
{
- Utils->SendChannelMessage(user->uuid, target.Get<Channel>(), details.text, target.status, details.exemptions, message_type);
+ Utils->SendChannelMessage(user->uuid, target.Get<Channel>(), details.text, target.status, details.tags_out, details.exemptions, message_type);
}
else if (target.type == MessageTarget::TYPE_SERVER)
{
const std::string* serverglob = target.Get<std::string>();
CmdBuilder par(user, message_type);
+ par.push_tags(details.tags_out);
par.push_back(*serverglob);
par.push_last(details.text);
par.Broadcast();
diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h
index 4f8875a02..fa2928687 100644
--- a/src/modules/m_spanningtree/main.h
+++ b/src/modules/m_spanningtree/main.h
@@ -83,6 +83,9 @@ class ModuleSpanningTree
public:
dynamic_reference<DNS::Manager> DNS;
+ /** Event provider for message tags. */
+ Events::ModuleEventProvider tagevprov;
+
ServerCommandManager CmdManager;
/** Set to true if inside a spanningtree call, to prevent sending
diff --git a/src/modules/m_spanningtree/postcommand.cpp b/src/modules/m_spanningtree/postcommand.cpp
index c7b4707b3..448bb3b54 100644
--- a/src/modules/m_spanningtree/postcommand.cpp
+++ b/src/modules/m_spanningtree/postcommand.cpp
@@ -39,6 +39,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
const bool encap = ((routing.type == ROUTE_TYPE_OPT_BCAST) || (routing.type == ROUTE_TYPE_OPT_UCAST));
CmdBuilder params(user, encap ? "ENCAP" : command.c_str());
+ params.push_tags(parameters.GetTags());
TreeServer* sdest = NULL;
if (routing.type == ROUTE_TYPE_OPT_BCAST)
@@ -100,7 +101,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
return;
// TODO OnBuildExemptList hook was here
CUList exempts;
- SendChannelMessage(user->uuid, c, parameters[1], pfx, exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
+ SendChannelMessage(user->uuid, c, parameters[1], pfx, parameters.GetTags(), exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
}
else if (dest[0] == '$')
{
diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp
index e54a528d9..56b9370ad 100644
--- a/src/modules/m_spanningtree/protocolinterface.cpp
+++ b/src/modules/m_spanningtree/protocolinterface.cpp
@@ -111,7 +111,8 @@ void SpanningTreeProtocolInterface::SendMessage(Channel* target, char status, co
{
const char* cmd = (msgtype == MSG_PRIVMSG ? "PRIVMSG" : "NOTICE");
CUList exempt_list;
- Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, cmd);
+ ClientProtocol::TagMap tags;
+ Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, tags, exempt_list, cmd);
}
void SpanningTreeProtocolInterface::SendMessage(User* target, const std::string& text, MessageType msgtype)
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index 36dd8bb93..878b34ad7 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -294,13 +294,17 @@ class TreeSocket : public BufferedSocket
/** Handle IRC line split
*/
- void Split(const std::string &line, std::string& prefix, std::string& command, CommandBase::Params& params);
+ void Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params);
/** Process complete line from buffer
*/
void ProcessLine(std::string &line);
- void ProcessConnectedLine(std::string& prefix, std::string& command, CommandBase::Params& params);
+ /** Process message tags received from a remote server. */
+ void ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags);
+
+ /** Process a message for a fully connected server. */
+ void ProcessConnectedLine(std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params);
/** Handle socket timeout from connect()
*/
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index 293cdd695..9ab8fc490 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -38,52 +38,61 @@ void TreeSocket::Error(CommandBase::Params& params)
SetError("received ERROR " + msg);
}
-void TreeSocket::Split(const std::string& line, std::string& prefix, std::string& command, CommandBase::Params& params)
+void TreeSocket::Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params)
{
+ std::string token;
irc::tokenstream tokens(line);
- if (!tokens.GetMiddle(prefix))
+ if (!tokens.GetMiddle(token))
return;
- if (prefix[0] == ':')
+ if (token[0] == '@')
{
- prefix.erase(prefix.begin());
-
- if (prefix.empty())
+ if (token.length() <= 1)
{
- this->SendError("BUG (?) Empty prefix received: " + line);
+ this->SendError("BUG: Received a message with empty tags: " + line);
return;
}
- if (!tokens.GetMiddle(command))
+
+ tags.assign(token, 1, std::string::npos);
+ if (!tokens.GetMiddle(token))
{
- this->SendError("BUG (?) Empty command received: " + line);
+ this->SendError("BUG: Received a message with no command: " + line);
return;
}
}
- else
- {
- command = prefix;
- prefix.clear();
- }
- if (command.empty())
- this->SendError("BUG (?) Empty command received: " + line);
- std::string param;
- while (tokens.GetTrailing(param))
+ if (token[0] == ':')
{
- params.push_back(param);
+ if (token.length() <= 1)
+ {
+ this->SendError("BUG: Received a message with an empty prefix: " + line);
+ return;
+ }
+
+ prefix.assign(token, 1, std::string::npos);
+ if (!tokens.GetMiddle(token))
+ {
+ this->SendError("BUG: Received a message with no command: " + line);
+ return;
+ }
}
+
+ command.assign(token);
+ while (tokens.GetTrailing(token))
+ params.push_back(token);
}
void TreeSocket::ProcessLine(std::string &line)
{
+ std::string tags;
std::string prefix;
std::string command;
CommandBase::Params params;
ServerInstance->Logs->Log(MODNAME, LOG_RAWIO, "S[%d] I %s", this->GetFd(), line.c_str());
- Split(line, prefix, command, params);
+ Split(line, tags, prefix, command, params);
if (command.empty())
return;
@@ -207,7 +216,7 @@ void TreeSocket::ProcessLine(std::string &line)
* Credentials have been exchanged, we've gotten their 'BURST' (or sent ours).
* Anything from here on should be accepted a little more reasonably.
*/
- this->ProcessConnectedLine(prefix, command, params);
+ this->ProcessConnectedLine(tags, prefix, command, params);
break;
case DYING:
break;
@@ -263,7 +272,35 @@ User* TreeSocket::FindSource(const std::string& prefix, const std::string& comma
return NULL;
}
-void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, CommandBase::Params& params)
+void TreeSocket::ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags)
+{
+ std::string tagkey;
+ std::string tagval;
+ const std::string::size_type p = tag.find('=');
+ if (p != std::string::npos)
+ {
+ // Tag has a value
+ tagkey.assign(tag, 0, p);
+ tagval.assign(tag, p + 1, std::string::npos);
+ }
+ else
+ {
+ tagkey.assign(tag);
+ }
+
+ const Events::ModuleEventProvider::SubscriberList& list = Utils->Creator->tagevprov.GetSubscribers();
+ for (Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i)
+ {
+ ClientProtocol::MessageTagProvider* const tagprov = static_cast<ClientProtocol::MessageTagProvider*>(*i);
+ const ModResult res = tagprov->OnClientProtocolProcessTag(source, tagkey, tagval);
+ if (res == MOD_RES_ALLOW)
+ tags.insert(std::make_pair(tagkey, ClientProtocol::MessageTagData(tagprov, tagval)));
+ else if (res == MOD_RES_DENY)
+ break;
+ }
+}
+
+void TreeSocket::ProcessConnectedLine(std::string& taglist, std::string& prefix, std::string& command, CommandBase::Params& params)
{
User* who = FindSource(prefix, command);
if (!who)
@@ -344,6 +381,10 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
else
{
ClientProtocol::TagMap tags;
+ std::string tag;
+ irc::sepstream tagstream(taglist, ';');
+ while (tagstream.GetToken(tag))
+ ProcessTag(who, tag, tags);
res = cmd->Handle(who, CommandBase::Params(params, tags));
if (res == CMD_INVALID)
throw ProtocolException("Error in command handler");
diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp
index 1224b1cf4..42eb80de5 100644
--- a/src/modules/m_spanningtree/utils.cpp
+++ b/src/modules/m_spanningtree/utils.cpp
@@ -352,9 +352,10 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name)
return NULL;
}
-void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const CUList& exempt_list, const char* message_type, TreeSocket* omit)
+void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit)
{
CmdBuilder msg(prefix, message_type);
+ msg.push_tags(tags);
msg.push_raw(' ');
if (status != 0)
msg.push_raw(status);
diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h
index e83e1c839..c6f5822fe 100644
--- a/src/modules/m_spanningtree/utils.h
+++ b/src/modules/m_spanningtree/utils.h
@@ -172,7 +172,7 @@ class SpanningTreeUtilities : public classbase
/** Sends a PRIVMSG or a NOTICE to a channel obeying an exempt list and an optional prefix
*/
- void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL);
+ void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL);
};
inline void SpanningTreeUtilities::DoOneToMany(const CmdBuilder& params)