diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/extra/xmlrpc.cpp | 113 | ||||
| -rw-r--r-- | modules/rpc/jsonrpc.cpp | 104 | ||||
| -rw-r--r-- | modules/rpc/rpc_main.cpp | 72 |
3 files changed, 157 insertions, 132 deletions
diff --git a/modules/extra/xmlrpc.cpp b/modules/extra/xmlrpc.cpp index 86cdaf9f7..1d9ab7762 100644 --- a/modules/extra/xmlrpc.cpp +++ b/modules/extra/xmlrpc.cpp @@ -42,56 +42,23 @@ private: xmlrpc_env_clean(&env); } + static xmlrpc_value *SerializeElement(xmlrpc_env &env, const RPC::Value &value); + + static void SerializeArray(xmlrpc_env &env, xmlrpc_value *value, const RPC::Array &array) + { + for (const auto &elem : array.GetReplies()) + { + auto *obj = SerializeElement(env, elem); + xmlrpc_array_append_item(&env, value, obj); + } + } + static void SerializeMap(xmlrpc_env &env, xmlrpc_value *value, const RPC::Map &map) { for (const auto &[k, v] : map.GetReplies()) { - xmlrpc_value *elem; - std::visit(overloaded - { - [&env, &elem](const RPC::Map &m) - { - elem = xmlrpc_struct_new(&env); - SerializeMap(env, elem, m); - }, - [&env, &elem](const Anope::string &s) - { - elem = xmlrpc_string_new_lp(&env, s.length(), s.c_str()); - }, - [&env, &elem](std::nullptr_t) - { - elem = xmlrpc_nil_new(&env); - }, - [&env, &elem](bool b) - { - elem = xmlrpc_bool_new(&env, b); - }, - [&env, &elem](double d) - { - elem = xmlrpc_double_new(&env, d); - }, - [&env, &elem](int64_t i) - { - elem = xmlrpc_i8_new(&env, i); - }, - [&env, &elem](uint64_t u) - { - // XML-RPC does not support unsigned data types. - if (u > INT64_MAX) - { - // We need to convert this to a string. - auto s = Anope::ToString(u); - elem = xmlrpc_string_new_lp(&env, s.length(), s.c_str()); - } - else - { - // We can fit this into a i8. - elem = xmlrpc_i8_new(&env, u); - } - }, - }, v); - - xmlrpc_struct_set_value_n(&env, value, k.c_str(), k.length(), elem); + auto *obj = SerializeElement(env, v); + xmlrpc_struct_set_value_n(&env, value, k.c_str(), k.length(), obj); } } @@ -206,6 +173,60 @@ public: } }; +xmlrpc_value *MyXMLRPCServiceInterface::SerializeElement(xmlrpc_env &env, const RPC::Value &value) +{ + xmlrpc_value *elem; + std::visit(overloaded + { + [&env, &elem](const RPC::Array &a) + { + elem = xmlrpc_array_new(&env); + SerializeArray(env, elem, a); + }, + [&env, &elem](const RPC::Map &m) + { + elem = xmlrpc_struct_new(&env); + SerializeMap(env, elem, m); + }, + [&env, &elem](const Anope::string &s) + { + elem = xmlrpc_string_new_lp(&env, s.length(), s.c_str()); + }, + [&env, &elem](std::nullptr_t) + { + elem = xmlrpc_nil_new(&env); + }, + [&env, &elem](bool b) + { + elem = xmlrpc_bool_new(&env, b); + }, + [&env, &elem](double d) + { + elem = xmlrpc_double_new(&env, d); + }, + [&env, &elem](int64_t i) + { + elem = xmlrpc_i8_new(&env, i); + }, + [&env, &elem](uint64_t u) + { + // XML-RPC does not support unsigned data types. + if (u > INT64_MAX) + { + // We need to convert this to a string. + auto s = Anope::ToString(u); + elem = xmlrpc_string_new_lp(&env, s.length(), s.c_str()); + } + else + { + // We can fit this into a i8. + elem = xmlrpc_i8_new(&env, u); + } + }, + }, value.Get()); + return elem; +} + class ModuleXMLRPC final : public Module { diff --git a/modules/rpc/jsonrpc.cpp b/modules/rpc/jsonrpc.cpp index b7c1f4042..ad46bcb13 100644 --- a/modules/rpc/jsonrpc.cpp +++ b/modules/rpc/jsonrpc.cpp @@ -59,46 +59,24 @@ private: yyjson_mut_doc_free(doc); } - static void SerializeMap(yyjson_mut_doc *doc, yyjson_mut_val *root, const char *key, const RPC::Map &map) + static yyjson_mut_val *SerializeElement(yyjson_mut_doc *doc, const RPC::Value &value); + + static void SerializeArray(yyjson_mut_doc *doc, yyjson_mut_val *value, const RPC::Array &array) { - auto *result = yyjson_mut_obj(doc); - for (const auto &reply : map.GetReplies()) - { - // Captured structured bindings are a C++20 extension. - const auto &k = reply.first; - std::visit(overloaded - { - [&doc, &result, &k](const RPC::Map &m) - { - SerializeMap(doc, result, k.c_str(), m); - }, - [&doc, &result, &k](const Anope::string &s) - { - yyjson_mut_obj_add_strn(doc, result, k.c_str(), s.c_str(), s.length()); - }, - [&doc, &result, &k](std::nullptr_t) - { - yyjson_mut_obj_add_null(doc, result, k.c_str()); - }, - [&doc, &result, &k](bool b) - { - yyjson_mut_obj_add_bool(doc, result, k.c_str(), b); - }, - [&doc, &result, &k](double d) - { - yyjson_mut_obj_add_real(doc, result, k.c_str(), d); - }, - [&doc, &result, &k](int64_t i) - { - yyjson_mut_obj_add_int(doc, result, k.c_str(), i); - }, - [&doc, &result, &k](uint64_t u) - { - yyjson_mut_obj_add_uint(doc, result, k.c_str(), u); - }, - }, reply.second); + for (const auto &elem : array.GetReplies()) + { + auto *obj = SerializeElement(doc, elem); + yyjson_mut_arr_add_val(value, obj); + } + } + + static void SerializeMap(yyjson_mut_doc *doc, yyjson_mut_val *value, const RPC::Map &map) + { + for (const auto &[k, v] : map.GetReplies()) + { + auto *obj = SerializeElement(doc, v); + yyjson_mut_obj_add_val(doc, value, k.c_str(), obj); } - yyjson_mut_obj_add_val(doc, root, key, result); } public: @@ -194,7 +172,11 @@ public: yyjson_mut_obj_add_strn(doc, root, "id", request.id.c_str(), request.id.length()); if (!request.GetReplies().empty()) - SerializeMap(doc, root, "result", request); + { + auto *result = yyjson_mut_obj(doc); + SerializeMap(doc, result, request); + yyjson_mut_obj_add_val(doc, root, "result", result); + } yyjson_mut_obj_add_str(doc, root, "jsonrpc", "2.0"); @@ -208,6 +190,50 @@ public: } }; +yyjson_mut_val *MyJSONRPCServiceInterface::SerializeElement(yyjson_mut_doc *doc, const RPC::Value &value) +{ + yyjson_mut_val *elem; + std::visit(overloaded + { + [&doc, &elem](const RPC::Array &a) + { + elem = yyjson_mut_arr(doc); + SerializeArray(doc, elem, a); + }, + [&doc, &elem](const RPC::Map &m) + { + elem = yyjson_mut_obj(doc); + SerializeMap(doc, elem, m); + }, + [&doc, &elem](const Anope::string &s) + { + elem = yyjson_mut_strn(doc, s.c_str(), s.length()); + }, + [&doc, &elem](std::nullptr_t) + { + elem = yyjson_mut_null(doc); + }, + [&doc, &elem](bool b) + { + elem = yyjson_mut_bool(doc, b); + }, + [&doc, &elem](double d) + { + elem = yyjson_mut_real(doc, d); + }, + [&doc, &elem](int64_t i) + { + elem = yyjson_mut_int(doc, i); + }, + [&doc, &elem](uint64_t u) + { + elem = yyjson_mut_uint(doc, u); + }, + }, value.Get()); + return elem; +} + + class ModuleJSONRPC final : public Module { diff --git a/modules/rpc/rpc_main.cpp b/modules/rpc/rpc_main.cpp index 7be09be22..c1e53e8dd 100644 --- a/modules/rpc/rpc_main.cpp +++ b/modules/rpc/rpc_main.cpp @@ -152,19 +152,16 @@ public: bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override { - request.ReplyInt("uptime", Anope::CurTime - Anope::StartTime); + request.Reply("uptime", Anope::CurTime - Anope::StartTime); request.Reply("uplinkname", Me->GetLinks().front()->GetName()); { - Anope::string buf; + auto &uplinkcapab = request.ReplyArray("uplinkcapab"); for (const auto &capab : Servers::Capab) - buf += " " + capab; - if (!buf.empty()) - buf.erase(buf.begin()); - request.Reply("uplinkcapab", buf); + uplinkcapab.Reply(capab); } - request.ReplyUInt("usercount", UserListByNick.size()); - request.ReplyUInt("maxusercount", MaxUserCount); - request.ReplyUInt("channelcount", ChannelList.size()); + request.Reply("usercount", UserListByNick.size()); + request.Reply("maxusercount", MaxUserCount); + request.Reply("channelcount", ChannelList.size()); return true; } }; @@ -192,35 +189,24 @@ public: if (c) { - auto &bans = request.ReplyMap("bans"); - bans.ReplyUInt("count", c->HasMode("BAN")); - int count = 0; + request.Reply("bancount", c->HasMode("BAN")); + auto &bans = request.ReplyArray("bans"); for (auto &ban : c->GetModeList("BAN")) - bans.Reply(Anope::ToString(++count), ban); + bans.Reply(ban); - auto &excepts = request.ReplyMap("excepts"); - excepts.ReplyUInt("count", c->HasMode("EXCEPT")); - count = 0; + request.Reply("exceptcount", c->HasMode("EXCEPT")); + auto &excepts = request.ReplyArray("excepts"); for (auto &except : c->GetModeList("EXCEPT")) - excepts.Reply(Anope::ToString(++count), except); + excepts.Reply(except); - auto &invites = request.ReplyMap("invites"); - invites.ReplyUInt("count", c->HasMode("INVITEOVERRIDE")); - count = 0; + request.Reply("invitecount", c->HasMode("INVITEOVERRIDE")); + auto &invites = request.ReplyArray("invites"); for (auto &invite : c->GetModeList("INVITEOVERRIDE")) - invites.Reply(Anope::ToString(++count), invite); + invites.Reply(invite); - Anope::string users; - for (Channel::ChanUserList::const_iterator it = c->users.begin(); it != c->users.end(); ++it) - { - ChanUserContainer *uc = it->second; - users += uc->status.BuildModePrefixList() + uc->user->nick + " "; - } - if (!users.empty()) - { - users.erase(users.length() - 1); - request.Reply("users", users); - } + auto &users = request.ReplyArray("users"); + for (const auto &[_, uc] : c->users) + users.Reply(uc->status.BuildModePrefixList() + uc->user->nick); if (!c->topic.empty()) request.Reply("topic", c->topic); @@ -228,8 +214,8 @@ public: if (!c->topic_setter.empty()) request.Reply("topicsetter", c->topic_setter); - request.ReplyInt("topictime", c->topic_time); - request.ReplyInt("topicts", c->topic_ts); + request.Reply("topictime", c->topic_time); + request.Reply("topicts", c->topic_ts); } return true; } @@ -266,8 +252,8 @@ public: if (!u->chost.empty()) request.Reply("chost", u->chost); request.Reply("ip", u->ip.addr()); - request.ReplyUInt("timestamp", u->timestamp); - request.ReplyUInt("signon", u->signon); + request.Reply("timestamp", u->timestamp); + request.Reply("signon", u->signon); if (u->IsIdentified()) { request.Reply("account", u->Account()->display); @@ -275,17 +261,9 @@ public: request.Reply("opertype", u->Account()->o->ot->GetName()); } - Anope::string channels; - for (User::ChanUserList::const_iterator it = u->chans.begin(); it != u->chans.end(); ++it) - { - ChanUserContainer *cc = it->second; - channels += cc->status.BuildModePrefixList() + cc->chan->name + " "; - } - if (!channels.empty()) - { - channels.erase(channels.length() - 1); - request.Reply("channels", channels); - } + auto &channels = request.ReplyArray("channels"); + for (const auto &[_, cc] : u->chans) + channels.Reply(cc->status.BuildModePrefixList() + cc->chan->name); } return true; } |
