summaryrefslogtreecommitdiff
path: root/modules/rpc/rpc_system.cpp
blob: ede4b770e9a767f4e7bba93f35238a3d8c381dfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 *
 * (C) 2010-2025 Anope Team
 * Contact us at team@anope.org
 *
 * Please read COPYING and README for further details.
 */

#include "module.h"
#include "modules/rpc.h"

// TODO:
//
// * system.getCapabilities
// * system.methodHelp
// * system.methodSignature

class AnopeDebugTypesRPCEvent final
	: public RPC::Event
{
public:
	AnopeDebugTypesRPCEvent()
		: RPC::Event("anope.debugTypes")
	{
	}

	bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
	{
		// For both the map type and array type we test that we can handle:
		//
		// * Arrays
		// * Maps
		// * Strings
		// * Null
		// * Boolean true
		// * Boolean false
		// * Doubles
		// * Signed integer that can fit into a 32-bit type.
		// * Signed integer that needs a 64-bit type (not supported by some
		//   XML-RPC clients).
		// * Unsigned integer that can fit into a 32-bit signed type.
		// * Unsigned integer that needs a 64-bit signed type (not supported by
		//   some XML-RPC clients).
		// * Unsigned integer that needs a 64-bit unsigned type (converted to a
		//   string when using the xmlrpc module).

		auto &root = request.Root();

		auto &array = root.ReplyArray("array");
		array.ReplyArray();
		array.ReplyMap();
		array.Reply("string");
		array.Reply(nullptr);
		array.Reply(true);
		array.Reply(false);
		array.Reply(42.42);
		array.Reply(int64_t(42));
		array.Reply(int64_t(INT32_MAX) + 42);
		array.Reply(uint64_t(42));
		array.Reply(uint64_t(INT32_MAX) + 42);
		array.Reply(uint64_t(INT64_MAX) + 42);

		root.ReplyMap("map");
		root.Reply("string", "string");
		root.Reply("null", nullptr);
		root.Reply("true", true);
		root.Reply("false", false);
		root.Reply("double", 42.42);
		root.Reply("int-small", int64_t(42));
		root.Reply("int-large", int64_t(INT32_MAX) + 42);
		root.Reply("uint-small", uint64_t(42));
		root.Reply("uint-medium", uint64_t(INT32_MAX) + 42);
		root.Reply("uint-large", uint64_t(INT64_MAX) + 42);

		return true;
	}
};

class SystemListMethodsRPCEvent final
	: public RPC::Event
{
public:
	SystemListMethodsRPCEvent()
		: RPC::Event("system.listMethods")
	{
	}

	bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
	{
		auto &root = request.Root<RPC::Array>();
		for (const auto &[event, _] : iface->GetEvents())
			root.Reply(event);
		return true;
	}
};

class ModuleRPCSystem final
	: public Module
{
private:
	ServiceReference<RPC::ServiceInterface> rpc;
	AnopeDebugTypesRPCEvent anopedebugtypesrpcevent;
	SystemListMethodsRPCEvent systemlistmethodsrpcevent;

public:
	ModuleRPCSystem(const Anope::string &modname, const Anope::string &creator)
		: Module(modname, creator, EXTRA | VENDOR)
		, rpc("RPCServiceInterface", "rpc")
	{
		if (!rpc)
			throw ModuleException("Unable to find RPC interface, is jsonrpc/xmlrpc loaded?");

#if DEBUG_BUILD
		rpc->Register(&anopedebugtypesrpcevent);
#endif
		rpc->Register(&systemlistmethodsrpcevent);
	}

	~ModuleRPCSystem() override
	{
		if (!rpc)
			return;

#if DEBUG_BUILD
		rpc->Unregister(&anopedebugtypesrpcevent);
#endif
		rpc->Unregister(&systemlistmethodsrpcevent);
	}
};

MODULE_INIT(ModuleRPCSystem)