mirror of
https://github.com/anope/anope.git
synced 2026-07-06 15:13:13 +02:00
Rework how the RPC interface stores its events.
This commit is contained in:
+15
-3
@@ -46,9 +46,21 @@ class RPCServiceInterface;
|
||||
|
||||
class RPCEvent
|
||||
{
|
||||
private:
|
||||
Anope::string event;
|
||||
|
||||
protected:
|
||||
RPCEvent(const Anope::string& e)
|
||||
: event(e)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~RPCEvent() = default;
|
||||
virtual bool Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) = 0;
|
||||
|
||||
const auto &GetEvent() const { return event; }
|
||||
|
||||
virtual void Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) = 0;
|
||||
};
|
||||
|
||||
class RPCServiceInterface
|
||||
@@ -57,9 +69,9 @@ class RPCServiceInterface
|
||||
public:
|
||||
RPCServiceInterface(Module *creator, const Anope::string &sname) : Service(creator, "RPCServiceInterface", sname) { }
|
||||
|
||||
virtual void Register(RPCEvent *event) = 0;
|
||||
virtual bool Register(RPCEvent *event) = 0;
|
||||
|
||||
virtual void Unregister(RPCEvent *event) = 0;
|
||||
virtual bool Unregister(RPCEvent *event) = 0;
|
||||
|
||||
virtual void Reply(RPCRequest &request) = 0;
|
||||
};
|
||||
|
||||
+20
-27
@@ -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)
|
||||
event->second->Run(this, client, request);
|
||||
|
||||
if (request.GetError())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (!request.GetReplies().empty())
|
||||
{
|
||||
this->Reply(request);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+18
-24
@@ -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;
|
||||
}
|
||||
|
||||
// If we reached this point nobody handled the event.
|
||||
SendError(reply, -32601, "Method not found", id);
|
||||
event->second->Run(this, client, request);
|
||||
|
||||
if (request.GetError())
|
||||
{
|
||||
SendError(reply, request.GetError()->first, request.GetError()->second, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
this->Reply(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+102
-34
@@ -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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void DoUser(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
|
||||
class UserRPCEvent final
|
||||
: public RPCEvent
|
||||
{
|
||||
public:
|
||||
UserRPCEvent()
|
||||
: RPCEvent("user")
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void DoNotice(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
|
||||
class NoticeRPCEvent final
|
||||
: public RPCEvent
|
||||
{
|
||||
public:
|
||||
NoticeRPCEvent()
|
||||
: RPCEvent("notice")
|
||||
{
|
||||
}
|
||||
|
||||
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(¬icerpcevent);
|
||||
}
|
||||
|
||||
~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(¬icerpcevent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user