summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-02-18 17:01:33 +0000
committerSadie Powell <sadie@witchery.services>2025-02-18 17:01:33 +0000
commit3c55fbe6509c1706d21136392a4bfb2295a99a35 (patch)
tree79b4ea204d2d75bdc098cfbc6492c137a4770b96 /modules
parent98320d130f6c74793d416526e892b11ca5619b91 (diff)
Rework how the RPC interface stores its events.
Diffstat (limited to 'modules')
-rw-r--r--modules/extra/xmlrpc.cpp47
-rw-r--r--modules/rpc/jsonrpc.cpp42
-rw-r--r--modules/rpc/rpc_main.cpp136
3 files changed, 140 insertions, 85 deletions
diff --git a/modules/extra/xmlrpc.cpp b/modules/extra/xmlrpc.cpp
index 582a5ab25..ca6856fd2 100644
--- a/modules/extra/xmlrpc.cpp
+++ b/modules/extra/xmlrpc.cpp
@@ -20,7 +20,7 @@ class MyXMLRPCServiceInterface final
, public HTTPPage
{
private:
- std::deque<RPCEvent *> events;
+ Anope::map<RPCEvent *> events;
void SendError(HTTPReply &reply, xmlrpc_env &env)
{
@@ -46,17 +46,14 @@ public:
{
}
- void Register(RPCEvent *event) override
+ bool Register(RPCEvent *event) override
{
- this->events.push_back(event);
+ return this->events.emplace(event->GetEvent(), event).second;
}
- void Unregister(RPCEvent *event) override
+ bool Unregister(RPCEvent *event) override
{
- std::deque<RPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
-
- if (it != this->events.end())
- this->events.erase(it);
+ return this->events.erase(event->GetEvent()) != 0;
}
bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) override
@@ -79,6 +76,14 @@ public:
request.name = method;
delete method;
+ auto event = this->events.find(request.name);
+ if (event == this->events.end())
+ {
+ xmlrpc_env_set_fault(&env, -32601, "Method not found");
+ SendError(reply, env);
+ return true;
+ }
+
auto paramcount = xmlrpc_array_size(&env, params);
for (auto idx = 0; idx < paramcount; ++idx)
{
@@ -113,28 +118,16 @@ public:
}
xmlrpc_DECREF(params);
- for (auto *e : this->events)
- {
- if (!e->Run(this, client, request))
- return false;
-
- if (request.GetError())
- {
- xmlrpc_env_set_fault(&env, request.GetError()->first, request.GetError()->second.c_str());
- SendError(reply, env);
- return true;
- }
+ event->second->Run(this, client, request);
- if (!request.GetReplies().empty())
- {
- this->Reply(request);
- return true;
- }
+ if (request.GetError())
+ {
+ xmlrpc_env_set_fault(&env, request.GetError()->first, request.GetError()->second.c_str());
+ SendError(reply, env);
+ return true;
}
- // If we reached this point nobody handled the event.
- xmlrpc_env_set_fault(&env, -32601, "Method not found");
- SendError(reply, env);
+ this->Reply(request);
return true;
}
diff --git a/modules/rpc/jsonrpc.cpp b/modules/rpc/jsonrpc.cpp
index 92a4765e9..8c16f4cc8 100644
--- a/modules/rpc/jsonrpc.cpp
+++ b/modules/rpc/jsonrpc.cpp
@@ -23,7 +23,7 @@ class MyJSONRPCServiceInterface final
, public HTTPPage
{
private:
- std::deque<RPCEvent *> events;
+ Anope::map<RPCEvent *> events;
void SendError(HTTPReply &reply, int64_t code, const Anope::string &message, const Anope::string &id)
{
@@ -63,16 +63,14 @@ public:
{
}
- void Register(RPCEvent *event) override
+ bool Register(RPCEvent *event) override
{
- this->events.push_back(event);
+ return this->events.emplace(event->GetEvent(), event).second;
}
- void Unregister(RPCEvent *event) override
+ bool Unregister(RPCEvent *event) override
{
- auto it = std::find(this->events.begin(), this->events.end(), event);
- if (it != this->events.end())
- this->events.erase(it);
+ return this->events.erase(event->GetEvent()) != 0;
}
bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) override
@@ -117,26 +115,22 @@ public:
yyjson_doc_free(doc);
- for (auto *e : this->events)
+ auto event = this->events.find(request.name);
+ if (event == this->events.end())
{
- if (!e->Run(this, client, request))
- return false;
-
- else if (request.GetError())
- {
- SendError(reply, request.GetError()->first, request.GetError()->second, id);
- return true;
- }
-
- else if (!request.GetReplies().empty())
- {
- this->Reply(request);
- return true;
- }
+ SendError(reply, -32601, "Method not found", id);
+ return true;
+ }
+
+ event->second->Run(this, client, request);
+
+ if (request.GetError())
+ {
+ SendError(reply, request.GetError()->first, request.GetError()->second, id);
+ return true;
}
- // If we reached this point nobody handled the event.
- SendError(reply, -32601, "Method not found", id);
+ this->Reply(request);
return true;
}
diff --git a/modules/rpc/rpc_main.cpp b/modules/rpc/rpc_main.cpp
index 5e33447ff..b5c263be1 100644
--- a/modules/rpc/rpc_main.cpp
+++ b/modules/rpc/rpc_main.cpp
@@ -57,32 +57,16 @@ public:
}
};
-class MyRPCEvent final
+class CommandRPCEvent final
: public RPCEvent
{
public:
- bool Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
+ CommandRPCEvent()
+ : RPCEvent("command")
{
- if (request.name == "command")
- this->DoCommand(iface, client, request);
- else if (request.name == "checkAuthentication")
- return this->DoCheckAuthentication(iface, client, request);
- else if (request.name == "stats")
- this->DoStats(iface, client, request);
- else if (request.name == "channel")
- this->DoChannel(iface, client, request);
- else if (request.name == "user")
- this->DoUser(iface, client, request);
- else if (request.name == "opers")
- this->DoOperType(iface, client, request);
- else if (request.name == "notice")
- this->DoNotice(iface, client, request);
-
- return true;
}
-private:
- void DoCommand(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
Anope::string service = request.data.size() > 0 ? request.data[0] : "";
Anope::string user = request.data.size() > 1 ? request.data[1] : "";
@@ -126,8 +110,18 @@ private:
if (!out.empty())
request.Reply("return", out);
}
+};
- static bool DoCheckAuthentication(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+class CheckAuthenticationRPCEvent final
+ : public RPCEvent
+{
+public:
+ CheckAuthenticationRPCEvent()
+ : RPCEvent("checkAuthentication")
+ {
+ }
+
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
Anope::string username = request.data.size() > 0 ? request.data[0] : "";
Anope::string password = request.data.size() > 1 ? request.data[1] : "";
@@ -135,16 +129,25 @@ private:
if (username.empty() || password.empty())
{
request.Error(-32602, "Invalid parameters");
- return true;
+ return;
}
auto *req = new RPCIdentifyRequest(me, request, client, iface, username, password);
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
req->Dispatch();
- return false;
+ }
+};
+
+class StatsRPCEvent final
+ : public RPCEvent
+{
+public:
+ StatsRPCEvent()
+ : RPCEvent("stats")
+ {
}
- static void DoStats(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
request.Reply("uptime", Anope::ToString(Anope::CurTime - Anope::StartTime));
request.Reply("uplinkname", Me->GetLinks().front()->GetName());
@@ -160,8 +163,18 @@ private:
request.Reply("maxusercount", Anope::ToString(MaxUserCount));
request.Reply("channelcount", Anope::ToString(ChannelList.size()));
}
+};
- static void DoChannel(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+class ChannelRPCEvent final
+ : public RPCEvent
+{
+public:
+ ChannelRPCEvent()
+ : RPCEvent("channel")
+ {
+ }
+
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
if (request.data.empty())
return;
@@ -209,8 +222,18 @@ private:
request.Reply("topicts", Anope::ToString(c->topic_ts));
}
}
+};
+
+class UserRPCEvent final
+ : public RPCEvent
+{
+public:
+ UserRPCEvent()
+ : RPCEvent("user")
+ {
+ }
- static void DoUser(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
if (request.data.empty())
return;
@@ -251,8 +274,18 @@ private:
}
}
}
+};
- static void DoOperType(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+class OpersRPCEvent final
+ : public RPCEvent
+{
+public:
+ OpersRPCEvent()
+ : RPCEvent("opers")
+ {
+ }
+
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
for (auto *ot : Config->MyOperTypes)
{
@@ -264,8 +297,18 @@ private:
request.Reply(ot->GetName(), perms);
}
}
+};
+
+class NoticeRPCEvent final
+ : public RPCEvent
+{
+public:
+ NoticeRPCEvent()
+ : RPCEvent("notice")
+ {
+ }
- static void DoNotice(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
{
Anope::string from = request.data.size() > 0 ? request.data[0] : "";
Anope::string to = request.data.size() > 1 ? request.data[1] : "";
@@ -275,7 +318,10 @@ private:
User *u = User::Find(to, true);
if (!bi || !u || message.empty())
+ {
+ request.Error(-32602, "Invalid parameters");
return;
+ }
u->SendMessage(bi, message);
}
@@ -284,25 +330,47 @@ private:
class ModuleRPCMain final
: public Module
{
+private:
ServiceReference<RPCServiceInterface> rpc;
-
- MyRPCEvent stats;
+ CommandRPCEvent commandrpcevent;
+ CheckAuthenticationRPCEvent checkauthenticationrpcevent;
+ StatsRPCEvent statsrpcevent;
+ ChannelRPCEvent channelrpcevent;
+ UserRPCEvent userrpcevent;
+ OpersRPCEvent opersrpcevent;
+ NoticeRPCEvent noticerpcevent;
public:
- ModuleRPCMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), rpc("RPCServiceInterface", "rpc")
+ ModuleRPCMain(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, EXTRA | VENDOR)
+ , rpc("RPCServiceInterface", "rpc")
{
me = this;
if (!rpc)
throw ModuleException("Unable to find RPC interface, is jsonrpc/xmlrpc loaded?");
- rpc->Register(&stats);
+ rpc->Register(&commandrpcevent);
+ rpc->Register(&checkauthenticationrpcevent);
+ rpc->Register(&statsrpcevent);
+ rpc->Register(&channelrpcevent);
+ rpc->Register(&userrpcevent);
+ rpc->Register(&opersrpcevent);
+ rpc->Register(&noticerpcevent);
}
~ModuleRPCMain() override
{
- if (rpc)
- rpc->Unregister(&stats);
+ if (!rpc)
+ return;
+
+ rpc->Unregister(&commandrpcevent);
+ rpc->Unregister(&checkauthenticationrpcevent);
+ rpc->Unregister(&statsrpcevent);
+ rpc->Unregister(&channelrpcevent);
+ rpc->Unregister(&userrpcevent);
+ rpc->Unregister(&opersrpcevent);
+ rpc->Unregister(&noticerpcevent);
}
};