From: Aki Tuomi Date: Fri, 8 Jan 2016 12:38:39 +0000 (+0200) Subject: Use Json11 instead of RapidJSON X-Git-Tag: dnsdist-1.0.0-alpha2~36^2~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fa2dd0e63ec6d5528fb82a68e7a3d9013c029db3;p=pdns Use Json11 instead of RapidJSON --- diff --git a/modules/remotebackend/httpconnector.cc b/modules/remotebackend/httpconnector.cc index db18969fb..5ac830911 100644 --- a/modules/remotebackend/httpconnector.cc +++ b/modules/remotebackend/httpconnector.cc @@ -47,47 +47,20 @@ HTTPConnector::~HTTPConnector() { delete d_socket; } -// converts json value into string -bool HTTPConnector::json2string(const rapidjson::Value &input, std::string &output) { - if (input.IsString()) output = input.GetString(); - else if (input.IsNull()) output = ""; - else if (input.IsUint64()) output = std::to_string(input.GetUint64()); - else if (input.IsInt64()) output = std::to_string(input.GetInt64()); - else if (input.IsUint()) output = std::to_string(input.GetUint()); - else if (input.IsInt()) output = std::to_string(input.GetInt()); - else return false; - return true; -} - -void HTTPConnector::addUrlComponent(const rapidjson::Value ¶meters, const char *element, std::stringstream& ss) { - rapidjson::Value nullval; +void HTTPConnector::addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss) { std::string sparam; - nullval.SetNull(); - const rapidjson::Value& param = (parameters.HasMember(element)?parameters[element]:nullval); - if (param.IsNull() == false) { - json2string(param, sparam); - ss << "/" << sparam; - } + if (parameters[element] != Json()) + ss << "/" << asString(parameters[element]); } -template std::string buildMemberListArgs(std::string prefix, const T* value) { +std::string HTTPConnector::buildMemberListArgs(std::string prefix, const Json& args) { std::stringstream stream; - for (rapidjson::Value::ConstMemberIterator itr = value->MemberBegin(); itr != value->MemberEnd(); itr++) { - stream << prefix << "[" << itr->name.GetString() << "]="; - - if (itr->value.IsUint64()) { - stream << itr->value.GetUint64(); - } else if (itr->value.IsInt64()) { - stream << itr->value.GetInt64(); - } else if (itr->value.IsUint()) { - stream << itr->value.GetUint(); - } else if (itr->value.IsInt()) { - stream << itr->value.GetInt(); - } else if (itr->value.IsBool()) { - stream << (itr->value.GetBool() ? 1 : 0); - } else if (itr->value.IsString()) { - stream << YaHTTP::Utility::encodeURL(itr->value.GetString(), false); + for(const auto& pair: args.object_items()) { + if (pair.second.is_bool()) { + stream << (pair.second.bool_value()?"1":"0"); + } else { + stream << prefix << "[" << pair.first << "]=" << this->asString(pair.second); } stream << "&"; @@ -97,7 +70,7 @@ template std::string buildMemberListArgs(std::string prefix, const T* } // builds our request (near-restful) -void HTTPConnector::restful_requestbuilder(const std::string &method, const rapidjson::Value ¶meters, YaHTTP::Request& req) +void HTTPConnector::restful_requestbuilder(const std::string &method, const Json& parameters, YaHTTP::Request& req) { std::stringstream ss; std::string sparam; @@ -125,18 +98,17 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi // create an empty post verb = "POST"; } else if (method == "setTSIGKey") { - req.POST()["algorithm"] = parameters["algorithm"].GetString(); - req.POST()["content"] = parameters["content"].GetString(); + req.POST()["algorithm"] = parameters["algorithm"].string_value(); + req.POST()["content"] = parameters["content"].string_value(); req.preparePost(); verb = "PATCH"; } else if (method == "deleteTSIGKey") { verb = "DELETE"; } else if (method == "addDomainKey") { - const rapidjson::Value& param = parameters["key"]; - json2string(param["flags"],sparam); - req.POST()["flags"] = sparam; - req.POST()["active"] = (param["active"].GetBool() ? "1" : "0"); - req.POST()["content"] = param["content"].GetString(); + const Json& param = parameters["key"]; + req.POST()["flags"] = asString(param["flags"]); + req.POST()["active"] = (param["active"].bool_value() ? "1" : "0"); + req.POST()["content"] = param["content"].string_value(); req.preparePost(); verb = "PUT"; } else if (method == "isMaster") { @@ -147,10 +119,8 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi addUrlComponent(parameters, "ip", ss); addUrlComponent(parameters, "domain", ss); // then we need to serialize rrset payload into POST - size_t index = 0; - for(rapidjson::Value::ConstValueIterator itr = parameters["nsset"].Begin(); itr != parameters["nsset"].End(); itr++) { - index++; - ss2 << buildMemberListArgs("nsset[" + std::to_string(index) + "]", itr) << "&"; + for(size_t index = 0; index < parameters["nsset"].array_items().size(); index++) { + ss2 << buildMemberListArgs("nsset[" + std::to_string(index) + "]", parameters["nsset"][index]) << "&"; } req.body = ss2.str().substr(0, ss2.str().size()-1); req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; @@ -159,17 +129,15 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi } else if (method == "createSlaveDomain") { addUrlComponent(parameters, "ip", ss); addUrlComponent(parameters, "domain", ss); - if (parameters.HasMember("account")) { - req.POST()["account"] = parameters["account"].GetString(); + if (parameters["account"].is_string()) { + req.POST()["account"] = parameters["account"].string_value(); } req.preparePost(); verb = "PUT"; } else if (method == "replaceRRSet") { std::stringstream ss2; - size_t index = 0; - for(rapidjson::Value::ConstValueIterator itr = parameters["rrset"].Begin(); itr != parameters["rrset"].End(); itr++) { - index++; - ss2 << buildMemberListArgs("rrset[" + std::to_string(index) + "]", itr); + for(size_t index = 0; index < parameters["rrset"].array_items().size(); index++) { + ss2 << buildMemberListArgs("rrset[" + std::to_string(index) + "]", parameters["rrset"][index]); } req.body = ss2.str(); req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; @@ -177,15 +145,18 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi verb = "PATCH"; } else if (method == "feedRecord") { addUrlComponent(parameters, "trxid", ss); - req.body = buildMemberListArgs("rr", ¶meters["rr"]); + req.body = buildMemberListArgs("rr", parameters["rr"]); req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; req.headers["content-length"] = std::to_string(req.body.size()); verb = "PATCH"; } else if (method == "feedEnts") { std::stringstream ss2; addUrlComponent(parameters, "trxid", ss); - for(rapidjson::Value::ConstValueIterator itr = parameters["nonterm"].Begin(); itr != parameters["nonterm"].End(); itr++) { - ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(itr->GetString(), false) << "&"; + for(const auto& param: parameters["nonterm"].array_items()) { + ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; + } + for(const auto& param: parameters["auth"].array_items()) { + ss2 << "auth[]=" << (param["auth"].bool_value()?"1":"0") << "&"; } req.body = ss2.str().substr(0, ss2.str().size()-1); req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; @@ -195,9 +166,12 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi std::stringstream ss2; addUrlComponent(parameters, "domain", ss); addUrlComponent(parameters, "trxid", ss); - ss2 << "times=" << parameters["times"].GetInt() << "&salt=" << YaHTTP::Utility::encodeURL(parameters["salt"].GetString(), false) << "&narrow=" << (parameters["narrow"].GetBool() ? 1 : 0) << "&"; - for(rapidjson::Value::ConstValueIterator itr = parameters["nonterm"].Begin(); itr != parameters["nonterm"].End(); itr++) { - ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(itr->GetString(), false) << "&"; + ss2 << "times=" << parameters["times"].int_value() << "&salt=" << YaHTTP::Utility::encodeURL(parameters["salt"].string_value(), false) << "&narrow=" << (parameters["narrow"].bool_value() ? 1 : 0) << "&"; + for(const auto& param: parameters["nonterm"].array_items()) { + ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; + } + for(const auto& param: parameters["auth"].array_items()) { + ss2 << "auth[]=" << (param["auth"].bool_value()?"1":"0") << "&"; } req.body = ss2.str().substr(0, ss2.str().size()-1); req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; @@ -212,18 +186,17 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi verb = "POST"; } else if (method == "calculateSOASerial") { addUrlComponent(parameters, "domain", ss); - req.body = buildMemberListArgs("sd", ¶meters["sd"]); + req.body = buildMemberListArgs("sd", parameters["sd"]); req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; req.headers["content-length"] = std::to_string(req.body.size()); verb = "POST"; } else if (method == "setDomainMetadata") { // copy all metadata values into post std::stringstream ss2; - const rapidjson::Value& param = parameters["value"]; // this one has values too - if (param.IsArray()) { - for(rapidjson::Value::ConstValueIterator i = param.Begin(); i != param.End(); i++) { - ss2 << "value[]=" << YaHTTP::Utility::encodeURL(i->GetString(), false) << "&"; + if (parameters["value"].is_array()) { + for(const auto& val: parameters["value"].array_items()) { + ss2 << "value[]=" << YaHTTP::Utility::encodeURL(val.string_value(), false) << "&"; } } req.body = ss2.str().substr(0, ss2.str().size()-1); @@ -234,19 +207,16 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi // this one is delete verb = "DELETE"; } else if (method == "setNotified") { - json2string(parameters["serial"],sparam); - req.POST()["serial"] = sparam; + req.POST()["serial"] = std::to_string(parameters["serial"].number_value()); req.preparePost(); verb = "PATCH"; } else if (method == "directBackendCmd") { - json2string(parameters["query"],sparam); - req.POST()["query"] = sparam; + req.POST()["query"] = parameters["query"].string_value(); req.preparePost(); verb = "POST"; } else if (method == "searchRecords" || method == "searchComments") { - json2string(parameters["pattern"],sparam); - req.GET()["pattern"] = sparam; - req.GET()["maxResults"] = std::to_string(parameters["maxResults"].GetInt()); + req.GET()["pattern"] = parameters["pattern"].string_value(); + req.GET()["maxResults"] = std::to_string(parameters["maxResults"].int_value()); verb = "GET"; } else { // perform normal get @@ -254,17 +224,16 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi } // put everything else into headers - for (rapidjson::Value::ConstMemberIterator iter = parameters.MemberBegin(); iter != parameters.MemberEnd(); ++iter) { - std::string member = iter->name.GetString(); + for(const auto& pair: parameters.object_items()) { + std::string member = pair.first; // whitelist header parameters if ((member == "trxid" || member == "local" || member == "remote" || member == "real-remote" || - member == "zone-id") && - json2string(parameters[member.c_str()], sparam)) { + member == "zone-id")) { std::string hdr = "x-remotebackend-" + member; - req.headers[hdr] = sparam; + req.headers[hdr] = pair.second.string_value(); } }; @@ -275,14 +244,11 @@ void HTTPConnector::restful_requestbuilder(const std::string &method, const rapi req.headers["accept"] = "application/json"; } -void HTTPConnector::post_requestbuilder(const rapidjson::Document &input, YaHTTP::Request& req) { - rapidjson::StringBuffer output; - rapidjson::Writer w(output); +void HTTPConnector::post_requestbuilder(const Json& input, YaHTTP::Request& req) { if (this->d_post_json) { + std::string out = input.dump(); req.setup("POST", d_url); // simple case, POST JSON into url. nothing fancy. - input.Accept(w); - std::string out(output.GetString(), output.Size()); req.headers["Content-Type"] = "text/javascript; charset=utf-8"; req.headers["Content-Length"] = std::to_string(out.size()); req.headers["accept"] = "application/json"; @@ -290,17 +256,16 @@ void HTTPConnector::post_requestbuilder(const rapidjson::Document &input, YaHTTP } else { std::stringstream url,content; // call url/method.suffix - input["parameters"].Accept(w); - url << d_url << "/" << input["method"].GetString() << d_url_suffix; + url << d_url << "/" << input["method"].string_value() << d_url_suffix; req.setup("POST", url.str()); // then build content - req.POST()["parameters"] = output.GetString(); + req.POST()["parameters"] = input["parameters"].dump(); req.preparePost(); req.headers["accept"] = "application/json"; } } -int HTTPConnector::send_message(const rapidjson::Document &input) { +int HTTPConnector::send_message(const Json& input) { int rv,ec,fd; std::vector members; @@ -313,7 +278,7 @@ int HTTPConnector::send_message(const rapidjson::Document &input) { if (d_post) post_requestbuilder(input, req); else - restful_requestbuilder(input["method"].GetString(), input["parameters"], req); + restful_requestbuilder(input["method"].string_value(), input["parameters"], req); rv = -1; req.headers["connection"] = "Keep-Alive"; // see if we can streamline requests (not needed, strictly speaking) @@ -385,7 +350,7 @@ int HTTPConnector::send_message(const rapidjson::Document &input) { return rv; } -int HTTPConnector::recv_message(rapidjson::Document &output) { +int HTTPConnector::recv_message(Json& output) { YaHTTP::AsyncResponseLoader arl; YaHTTP::Response resp; @@ -433,15 +398,11 @@ int HTTPConnector::recv_message(rapidjson::Document &output) { return -1; } - rapidjson::StringStream ss(resp.body.c_str()); int rv = -1; - output.ParseStream<0>(ss); - - // offer whatever we read in send_message - if (output.HasParseError() == false) - rv = rd; - else - rv = -1; + std::string err; + output = Json::parse(resp.body, err); + if (output != nullptr) return resp.body.size(); + L< -#include -#include #include "remotebackend.hh" PipeConnector::PipeConnector(std::map options) { @@ -96,32 +93,22 @@ void PipeConnector::launch() { no way to log this either - only thing we can do is make sure that our parent catches this soonest! */ } - rapidjson::Value val; - rapidjson::Document init,res; - init.SetObject(); - val = "initialize"; + Json::array parameters; + Json msg = Json(Json::object{ + { "method", "initialize" }, + { "parameters", Json(options) }, + }); - init.AddMember("method",val, init.GetAllocator()); - val.SetObject(); - init.AddMember("parameters", val, init.GetAllocator()); - - for(auto i = options.begin(); i != options.end(); i++) { - val = i->second.c_str(); - init["parameters"].AddMember(i->first.c_str(), val, init.GetAllocator()); - } - - this->send(init); - if (this->recv(res)==false) { + this->send(msg); + msg = nullptr; + if (this->recv(msg)==false) { L< w(output); - input.Accept(w); - auto line = std::string(output.GetString(), output.Size()); + auto line = input.dump(); launch(); line.append(1,'\n'); @@ -140,11 +127,10 @@ int PipeConnector::send_message(const rapidjson::Document &input) return sent; } -int PipeConnector::recv_message(rapidjson::Document &output) +int PipeConnector::recv_message(Json& output) { std::string receive; - rapidjson::GenericReader , rapidjson::MemoryPoolAllocator<> > r; - std::string tmp; + std::string err; std::string s_output; launch(); @@ -168,10 +154,9 @@ int PipeConnector::recv_message(rapidjson::Document &output) throw PDNSException("Child closed pipe"); s_output.append(receive); - rapidjson::StringStream ss(s_output.c_str()); - output.ParseStream<0>(ss); - if (output.HasParseError() == false) - return s_output.size(); + // see if it can be parsed + output = Json::parse(s_output, err); + if (output != nullptr) return s_output.size(); } return 0; } diff --git a/modules/remotebackend/remotebackend.cc b/modules/remotebackend/remotebackend.cc index bd5ea1bfd..1b10a9095 100644 --- a/modules/remotebackend/remotebackend.cc +++ b/modules/remotebackend/remotebackend.cc @@ -3,7 +3,6 @@ #endif #include "remotebackend.hh" - static const char *kBackendId = "[RemoteBackend]"; /** @@ -11,42 +10,32 @@ static const char *kBackendId = "[RemoteBackend]"; * we need to do some treatment to the value before * sending it downwards. */ -bool Connector::send(rapidjson::Document &value) { - return send_message(value); +bool Connector::send(Json& value) { + return send_message(value)>0; } -/** +/** * Helper for handling receiving of data. - * Basically what happens here is that we check + * Basically what happens here is that we check * that the receiving happened ok, and extract - * result. Logging is performed here, too. + * result. Logging is performed here, too. */ -bool Connector::recv(rapidjson::Document &value) { +bool Connector::recv(Json& value) { if (recv_message(value)>0) { bool rv = true; // check for error - if (!value.HasMember("result")) { - return false; - } - if (!value["result"].IsObject() && getBool(value["result"]) == false) { - rv = false; - } - if (value.HasMember("log")) { - rapidjson::Value& messages = value["log"]; - if (messages.IsArray()) { - // log em all - for (rapidjson::Value::ValueIterator iter = messages.Begin(); iter != messages.End(); ++iter) - L<d_connstr = getArg("connection-string"); - this->d_result = NULL; this->d_dnssec = mustDo("dnssec"); this->d_index = -1; this->d_trxid = 0; - + build(); } RemoteBackend::~RemoteBackend() { - if (connector != NULL) { + if (connector != NULL) { delete connector; } } -bool RemoteBackend::send(rapidjson::Document &value) { +bool RemoteBackend::send(Json& value) { try { return connector->send(value); } catch (PDNSException &ex) { @@ -80,7 +68,7 @@ bool RemoteBackend::send(rapidjson::Document &value) { return false; } -bool RemoteBackend::recv(rapidjson::Document &value) { +bool RemoteBackend::recv(Json& value) { try { return connector->recv(value); } catch (PDNSException &ex) { @@ -95,7 +83,7 @@ bool RemoteBackend::recv(rapidjson::Document &value) { } -/** +/** * Builds connector based on options * Currently supports unix,pipe and http */ @@ -156,79 +144,64 @@ int RemoteBackend::build() { return -1; } -/** +/** * The functions here are just remote json stubs that send and receive the method call - * data is mainly left alone, some defaults are assumed. + * data is mainly left alone, some defaults are assumed. */ void RemoteBackend::lookup(const QType &qtype, const DNSName& qdomain, DNSPacket *pkt_p, int zoneId) { - rapidjson::Document query; - rapidjson::Value parameters; - - if (d_index != -1) + if (d_index != -1) throw PDNSException("Attempt to lookup while one running"); - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "lookup", query.GetAllocator()) - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "qtype", qtype.getName().c_str(), query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(parameters, "qname", qdomain, query.GetAllocator()); - string localIP="0.0.0.0"; string remoteIP="0.0.0.0"; string realRemote="0.0.0.0/0"; + if (pkt_p) { localIP=pkt_p->getLocal(); realRemote = pkt_p->getRealRemote().toString(); remoteIP = pkt_p->getRemote(); } - JSON_ADD_MEMBER(parameters, "remote", remoteIP.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "local", localIP.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "real-remote", realRemote.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "zone-id", zoneId, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); - - d_result = new rapidjson::Document(); + Json query = Json::object{ + { "method", "lookup" }, + { "parameters", Json::object{ + { "qtype", qtype.getName() }, + { "qname", qdomain.toString() }, + { "remote", remoteIP }, + { "local", localIP }, + { "real-remote", realRemote }, + { "zone-id", zoneId } + }} + }; - if (this->send(query) == false || this->recv(*d_result) == false) { - delete d_result; + if (this->send(query) == false || this->recv(d_result) == false) { return; } // OK. we have result parameters in result. do not process empty result. - if ((*d_result)["result"].IsArray() == false || (*d_result)["result"].Size() < 1) { - delete d_result; - return; - } + if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) + return; d_index = 0; } bool RemoteBackend::list(const DNSName& target, int domain_id, bool include_disabled) { - rapidjson::Document query; - rapidjson::Value parameters; - if (d_index != -1) throw PDNSException("Attempt to lookup while one running"); - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "list", query.GetAllocator()); - query["method"] = "list"; - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "zonename", target, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "domain-id", domain_id, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); - - d_result = new rapidjson::Document(); + Json query = Json::object{ + { "method", "list" }, + { "parameters", Json::object{ + { "zonename", target.toString() }, + { "domain-id", domain_id }, + { "include-disabled", include_disabled } + }} + }; - if (this->send(query) == false || this->recv(*d_result) == false) { - delete d_result; + if (this->send(query) == false || this->recv(d_result) == false) + return false; + if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) return false; - } - if ((*d_result)["result"].IsArray() == false || (*d_result)["result"].Size() < 1) { - delete d_result; - return false; - } d_index = 0; return true; @@ -237,86 +210,78 @@ bool RemoteBackend::list(const DNSName& target, int domain_id, bool include_disa bool RemoteBackend::get(DNSResourceRecord &rr) { if (d_index == -1) return false; - rapidjson::Value value; - - value = ""; - rr.qtype = getString(JSON_GET((*d_result)["result"][d_index], "qtype", value)); - rr.qname = DNSName(getString(JSON_GET((*d_result)["result"][d_index], "qname", value))); + rr.qtype = stringFromJson(d_result["result"][d_index], "qtype"); + rr.qname = DNSName(stringFromJson(d_result["result"][d_index], "qname")); rr.qclass = QClass::IN; - rr.content = getString(JSON_GET((*d_result)["result"][d_index], "content",value)); - value = -1; - rr.ttl = getInt(JSON_GET((*d_result)["result"][d_index], "ttl",value)); - rr.domain_id = getInt(JSON_GET((*d_result)["result"][d_index],"domain_id",value)); - value = 1; - if (d_dnssec) - rr.auth = getInt(JSON_GET((*d_result)["result"][d_index],"auth", value)); + rr.content = stringFromJson(d_result["result"][d_index], "content"); + rr.ttl = intFromJson(d_result["result"][d_index], "ttl", 0); + rr.domain_id = intFromJson(d_result["result"][d_index], "domain_id", -1); + if (d_dnssec) + rr.auth = intFromJson(d_result["result"][d_index], "auth", 1); else rr.auth = 1; - value = 0; - rr.scopeMask = getInt(JSON_GET((*d_result)["result"][d_index],"scopeMask", value)); - + rr.scopeMask = intFromJson(d_result["result"][d_index], "scopeMask", 0); d_index++; - - // id index is out of bounds, we know the results end here. - if (d_index == static_cast((*d_result)["result"].Size())) { - delete d_result; - d_result = NULL; + + // id index is out of bounds, we know the results end here. + if (d_index == static_cast(d_result["result"].array_items().size())) { + d_result = Json(); d_index = -1; } return true; } bool RemoteBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, DNSName& unhashed, std::string& before, std::string& after) { - rapidjson::Document query,answer; - rapidjson::Value parameters; // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getBeforeAndAfterNamesAbsolute", query.GetAllocator()); - - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "id", id, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "qname", qname.c_str(), query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "getBeforeAndAfterNamesAbsolute" }, + { "parameters", Json::object { + { "id", Json(static_cast(id)) }, + { "qname", qname } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - unhashed = DNSName(getString(answer["result"]["unhashed"])); - before = getString(answer["result"]["before"]); - after = getString(answer["result"]["after"]); - + unhashed = DNSName(stringFromJson(answer["result"], "unhashed")); + before = ""; + after = ""; + if (answer["result"]["before"] != Json()) + before = stringFromJson(answer["result"], "before"); + if (answer["result"]["after"] != Json()) + after = stringFromJson(answer["result"], "after"); + return true; } bool RemoteBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getAllDomainMetadata", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "getAllDomainMetadata" }, + { "parameters", Json::object { + { "name", name.toString() } + }} + }; if (this->send(query) == false) return false; meta.clear(); + Json answer; // not mandatory to implement if (this->recv(answer) == false) return true; - if (answer["result"].IsObject()) { - for (rapidjson::Value::MemberIterator kind = answer["result"].MemberBegin(); kind != answer["result"].MemberEnd(); kind++) { - if (kind->value.IsArray()) { - for(rapidjson::Value::ValueIterator content = kind->value.Begin(); content != kind->value.End(); content++) - meta[kind->name.GetString()].push_back(getString(*content)); - } else { - meta[kind->name.GetString()].push_back(getString(kind->value)); - } + for(const auto& pair: answer["result"].object_items()) { + if (pair.second.is_array()) { + for(const auto& val: pair.second.array_items()) + meta[pair.first].push_back(asString(val)); + } else { + meta[pair.first].push_back(asString(pair.second)); } } @@ -324,110 +289,95 @@ bool RemoteBackend::getAllDomainMetadata(const DNSName& name, std::map& meta) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getDomainMetadata", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "kind", kind.c_str(), query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "getDomainMetadata" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "kind", kind } + }} + }; if (this->send(query) == false) return false; meta.clear(); + Json answer; // not mandatory to implement if (this->recv(answer) == false) return true; - if (answer["result"].IsArray()) { - for(rapidjson::Value::ValueIterator iter = answer["result"].Begin(); iter != answer["result"].End(); iter++) { - meta.push_back(getString(*iter)); - } - } else if (answer["result"].IsString()) { - meta.push_back(answer["result"].GetString()); + if (answer["result"].is_array()) { + for(const auto& row: answer["result"].array_items()) + meta.push_back(row.string_value()); + } else if (answer["result"].is_string()) { + meta.push_back(answer["result"].string_value()); } return true; } bool RemoteBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) { - rapidjson::Document query,answer; - rapidjson::Value parameters,val; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "setDomainMetadata", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "kind", kind.c_str(), query.GetAllocator()); - val.SetArray(); - for(const auto& value: meta) { - val.PushBack(value.c_str(), query.GetAllocator()); - } - parameters.AddMember("value", val, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "setDomainMetadata" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "kind", kind }, + { "value", meta } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - return getBool(answer["result"]); + return boolFromJson(answer, "result", false); } bool RemoteBackend::getDomainKeys(const DNSName& name, unsigned int kind, std::vector& keys) { - rapidjson::Document query,answer; - rapidjson::Value parameters; // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getDomainKeys", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "kind", kind, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "getDomainKeys" }, + { "parameters", Json::object{ + { "name", name.toString() }, + { "kind", static_cast(kind) } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; keys.clear(); - for(rapidjson::Value::ValueIterator iter = answer["result"].Begin(); iter != answer["result"].End(); iter++) { - DNSBackend::KeyData key; - if (!(*iter).IsObject()) - throw PDNSException("Invalid reply to getDomainKeys, expected array of hashes, got something else"); - - if (!(*iter).HasMember("id") || - !(*iter).HasMember("flags") || - !(*iter).HasMember("active") || - !(*iter).HasMember("content")) - throw PDNSException("Invalid reply to getDomainKeys, missing keys in key hash"); - - key.id = getUInt((*iter)["id"]); - key.flags = getUInt((*iter)["flags"]); - key.active = getBool((*iter)["active"]); - key.content = getString((*iter)["content"]); - keys.push_back(key); + for(const auto& jsonKey: answer["result"].array_items()) { + DNSBackend::KeyData key; + key.id = intFromJson(jsonKey, "id"); + key.flags = intFromJson(jsonKey, "flags"); + key.active = boolFromJson(jsonKey, "active"); + key.content = stringFromJson(jsonKey, "content"); + keys.push_back(key); } return true; } -bool RemoteBackend::removeDomainKey(const DNSName& name, unsigned int id) { - rapidjson::Document query,answer; - rapidjson::Value parameters; +bool RemoteBackend::removeDomainKey(const DNSName& name, unsigned int id) { // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "removeDomainKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "id", id, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "removeDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "id", static_cast(id) } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; @@ -435,42 +385,41 @@ bool RemoteBackend::removeDomainKey(const DNSName& name, unsigned int id) { } int RemoteBackend::addDomainKey(const DNSName& name, const KeyData& key) { - rapidjson::Document query,answer; - rapidjson::Value parameters,jkey; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "addDomainKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - jkey.SetObject(); - JSON_ADD_MEMBER(jkey, "flags", key.flags, query.GetAllocator()); - JSON_ADD_MEMBER(jkey, "active", key.active, query.GetAllocator()); - JSON_ADD_MEMBER(jkey, "content", key.content.c_str(), query.GetAllocator()); - parameters.AddMember("key", jkey, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "addDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "key", Json::object { + { "flags", static_cast(key.flags) }, + { "active", key.active }, + { "content", key.content } + }} + }} + }; + + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - return getInt(answer["result"]); + return intFromJson(answer,"result",0); } bool RemoteBackend::activateDomainKey(const DNSName& name, unsigned int id) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "activateDomainKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "id", id, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "activateDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "id", static_cast(id) } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; @@ -478,19 +427,18 @@ bool RemoteBackend::activateDomainKey(const DNSName& name, unsigned int id) { } bool RemoteBackend::deactivateDomainKey(const DNSName& name, unsigned int id) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "deactivateDomainKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "id", id, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "deactivateDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "id", static_cast(id) } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; @@ -502,44 +450,40 @@ bool RemoteBackend::doesDNSSEC() { } bool RemoteBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getTSIGKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "getTSIGKey" }, + { "parameters", Json::object { + { "name", name.toString() } + }} + }; + + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - if (!answer["result"].IsObject() || - !answer["result"].HasMember("algorithm") || - !answer["result"].HasMember("content")) - throw PDNSException("Invalid response to getTSIGKey, missing field(s)"); + (*algorithm) = DNSName(stringFromJson(answer["result"], "algorithm")); + (*content) = stringFromJson(answer["result"], "content"); - (*algorithm) = DNSName(getString(answer["result"]["algorithm"])); - content->assign(getString(answer["result"]["content"])); - return true; } bool RemoteBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const std::string& content) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "setTSIGKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(parameters, "algorithm", algorithm, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "content", content.c_str(), query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + + Json query = Json::object{ + { "method", "setTSIGKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "algorithm", algorithm.toString() }, + { "content", content } + }} + }; + + Json answer; if (connector->send(query) == false || connector->recv(answer) == false) return false; @@ -547,16 +491,16 @@ bool RemoteBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, co } bool RemoteBackend::deleteTSIGKey(const DNSName& name) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "deleteTSIGKey", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", name, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "deleteTSIGKey" }, + { "parameters", Json::object { + { "name", name.toString() } + }} + }; + + Json answer; if (connector->send(query) == false || connector->recv(answer) == false) return false; @@ -564,78 +508,55 @@ bool RemoteBackend::deleteTSIGKey(const DNSName& name) { } bool RemoteBackend::getTSIGKeys(std::vector& keys) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - // no point doing dnssec if it's not supported if (d_dnssec == false) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getTSIGKeys", query.GetAllocator()); - parameters.SetObject(); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "getTSIGKeys" }, + { "parameters", Json::object { + }} + }; + Json answer; if (connector->send(query) == false || connector->recv(answer) == false) return false; - // expect array - if (answer["result"].IsArray()) { - for(rapidjson::Value::ValueIterator iter = answer["result"].Begin(); iter != answer["result"].End(); iter++) { - struct TSIGKey key; - rapidjson::Value value; - value = ""; - key.name = DNSName(getString(JSON_GET((*iter), "name", value))); - key.algorithm = DNSName(getString(JSON_GET((*iter), "algorithm", value))); - key.key = getString(JSON_GET((*iter), "content", value)); - - if (key.name.empty() || - key.algorithm.empty() || - key.key.empty()) - throw PDNSException("Invalid reply for getTSIGKeys query"); - - keys.push_back(key); - } + for(const auto& jsonKey: answer["result"].array_items()) { + struct TSIGKey key; + key.name = DNSName(stringFromJson(jsonKey, "name")); + key.algorithm = DNSName(stringFromJson(jsonKey, "algorithm")); + key.key = stringFromJson(jsonKey, "content"); + keys.push_back(key); } return true; } bool RemoteBackend::getDomainInfo(const DNSName& domain, DomainInfo &di) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - rapidjson::Value value; - std::string kind; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "getDomainInfo", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "name", domain, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + if (domain.empty()) return false; + Json query = Json::object{ + { "method", "getDomainInfo" }, + { "parameters", Json::object { + { "name", domain.toString() } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - // make sure we got zone & kind - if (!answer["result"].IsObject() || !answer["result"].HasMember("zone")) { - L<(doubleFromJson(answer["result"], "notified_serial", -1)); + di.serial = static_cast(doubleFromJson(answer["result"], "serial", 0)); + di.last_check = static_cast(doubleFromJson(answer["result"], "last_check", 0)); + + string kind = ""; + if (answer["result"]["kind"].is_string()) { + kind = stringFromJson(answer["result"], "kind"); } - di.notified_serial = getInt(JSON_GET(answer["result"], "notified_serial", value)); - value = 0; - di.serial = getInt(JSON_GET(answer["result"],"serial", value)); - di.last_check = getInt(JSON_GET(answer["result"],"last_check", value)); - value = "native"; - kind = getString(JSON_GET(answer["result"], "kind", value)); if (kind == "master") { di.kind = DomainInfo::Master; } else if (kind == "slave") { @@ -648,16 +569,15 @@ bool RemoteBackend::getDomainInfo(const DNSName& domain, DomainInfo &di) { } void RemoteBackend::setNotified(uint32_t id, uint32_t serial) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "setNotified", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "id", id, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "serial", serial, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); - + Json query = Json::object{ + { "method", "setNotified" }, + { "parameters", Json::object { + { "id", static_cast(id) }, + { "serial", static_cast(serial) } + }} + }; + + Json answer; if (this->send(query) == false || this->recv(answer) == false) { L<send(query) == false || this->recv(answer) == false) return false; @@ -682,33 +602,31 @@ bool RemoteBackend::isMaster(const DNSName& name, const string &ip) bool RemoteBackend::superMasterBackend(const string &ip, const DNSName& domain, const vector&nsset, string* nameserver, string *account, DNSBackend **ddb) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - rapidjson::Value rrset; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "superMasterBackend", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "ip", ip.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(parameters, "domain", domain, query.GetAllocator()); - rrset.SetArray(); - rrset.Reserve(nsset.size(), query.GetAllocator()); - for(rapidjson::SizeType i = 0; i < nsset.size(); i++) { - rapidjson::Value rr; - rr.SetObject(); - JSON_ADD_MEMBER(rr, "qtype", nsset[i].qtype.getName().c_str(), query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(rr, "qname", nsset[i].qname, query.GetAllocator()); - JSON_ADD_MEMBER(rr, "qclass", QClass::IN, query.GetAllocator()); - JSON_ADD_MEMBER(rr, "content", nsset[i].content.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(rr, "ttl", nsset[i].ttl, query.GetAllocator()); - JSON_ADD_MEMBER(rr, "auth", nsset[i].auth, query.GetAllocator()); - rrset.PushBack(rr, query.GetAllocator()); + Json::array rrset; + + for(const auto& ns: nsset) { + rrset.push_back(Json::object{ + { "qtype", ns.qtype.getName() }, + { "qname", ns.qname.toString() }, + { "qclass", QClass::IN }, + { "content", ns.content }, + { "ttl", static_cast(ns.ttl) }, + { "auth", ns.auth } + }); } - parameters.AddMember("nsset", rrset, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + + Json query = Json::object{ + { "method", "superMasterBackend" }, + { "parameters", Json::object { + { "ip", ip }, + { "domain", domain.toString() }, + { "nsset", rrset } + }} + }; *ddb = 0; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; @@ -716,61 +634,56 @@ bool RemoteBackend::superMasterBackend(const string &ip, const DNSName& domain, *ddb = this; // we allow simple true as well... - if (answer["result"].IsObject()) { - if (answer["result"].HasMember("account")) - *account = getString(answer["result"]["account"]); - if (answer["result"].HasMember("nameserver")) - *nameserver = getString(answer["result"]["nameserver"]); + if (answer["result"].is_object()) { + *account = stringFromJson(answer["result"], "account"); + *nameserver = stringFromJson(answer["result"], "nameserver"); } + return true; } bool RemoteBackend::createSlaveDomain(const string &ip, const DNSName& domain, const string& nameserver, const string &account) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "createSlaveDomain", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "ip", ip.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(parameters, "domain", domain, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "nameserver", nameserver.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "account", account.c_str(), query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "createSlaveDomain" }, + { "parameters", Json::object { + { "ip", ip }, + { "domain", domain.toString() }, + { "nameserver", nameserver }, + { "account", account }, + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; return true; } bool RemoteBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qtype, const vector& rrset) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - rapidjson::Value rj_rrset; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "replaceRRSet", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(parameters, "qname", qname, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "qtype", qtype.getName().c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - - rj_rrset.SetArray(); - rj_rrset.Reserve(rrset.size(), query.GetAllocator()); - - for(rapidjson::SizeType i = 0; i < rrset.size(); i++) { - rapidjson::Value rr; - rr.SetObject(); - JSON_ADD_MEMBER(rr, "qtype", rrset[i].qtype.getName().c_str(), query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(rr, "qname", rrset[i].qname, query.GetAllocator()); - JSON_ADD_MEMBER(rr, "qclass", QClass::IN, query.GetAllocator()); - JSON_ADD_MEMBER(rr, "content", rrset[i].content.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(rr, "ttl", rrset[i].ttl, query.GetAllocator()); - JSON_ADD_MEMBER(rr, "auth", rrset[i].auth, query.GetAllocator()); - rj_rrset.PushBack(rr, query.GetAllocator()); + Json::array json_rrset; + for(const auto& rr: rrset) { + json_rrset.push_back(Json::object{ + { "qtype", rr.qtype.getName() }, + { "qname", rr.qname.toString() }, + { "qclass", QClass::IN }, + { "content", rr.content }, + { "ttl", static_cast(rr.ttl) }, + { "auth", rr.auth } + }); } - parameters.AddMember("rrset", rj_rrset, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "replaceRRSet" }, + { "parameters", Json::object { + { "domain_id", static_cast(domain_id) }, + { "qname", qname.toString() }, + { "qtype", qtype.getName() }, + { "trxid", static_cast(d_trxid) }, + { "rrset", json_rrset } + }} + }; + + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; @@ -778,96 +691,93 @@ bool RemoteBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const } bool RemoteBackend::feedRecord(const DNSResourceRecord &rr, string *ordername) { - rapidjson::Document query,answer; - rapidjson::Value parameters,rj_rr; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "feedRecord", query.GetAllocator()); - parameters.SetObject(); - rj_rr.SetObject(); - JSON_ADD_MEMBER(rj_rr, "qtype", rr.qtype.getName().c_str(), query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(rj_rr, "qname", rr.qname, query.GetAllocator()); - JSON_ADD_MEMBER(rj_rr, "qclass", QClass::IN, query.GetAllocator()); - JSON_ADD_MEMBER(rj_rr, "content", rr.content.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(rj_rr, "ttl", rr.ttl, query.GetAllocator()); - JSON_ADD_MEMBER(rj_rr, "auth", rr.auth, query.GetAllocator()); - parameters.AddMember("rr", rj_rr, query.GetAllocator()); - - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - - if (ordername) { - JSON_ADD_MEMBER(parameters, "ordername", ordername->c_str(), query.GetAllocator()); - } - - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "feedRecord" }, + { "parameters", Json::object{ + { "rr", Json::object{ + { "qtype", rr.qtype.getName() }, + { "qname", rr.qname.toString() }, + { "qclass", QClass::IN }, + { "content", rr.content }, + { "ttl", static_cast(rr.ttl) }, + { "auth", rr.auth }, + { "ordername", (ordername==nullptr?Json():*ordername) } + }}, + { "trxid", static_cast(d_trxid) }, + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; return true; // XXX FIXME this API should not return 'true' I think -ahu } bool RemoteBackend::feedEnts(int domain_id, map& nonterm) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - rapidjson::Value nts; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "feedEnts", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - nts.SetArray(); - for(const auto& t: nonterm) { - rapidjson::Value value(t.first.toString().c_str(), query.GetAllocator()); - nts.PushBack(value, query.GetAllocator()); - } - parameters.AddMember("nonterm", nts, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json::array nts; + + for(const auto& t: nonterm) + nts.push_back(Json::object{ + { "nonterm", t.first.toString() }, + { "auth", t.second } + }); + + Json query = Json::object{ + { "method", "feedEnts" }, + { "parameters", Json::object{ + { "domain_id", domain_id }, + { "trxid", static_cast(d_trxid) }, + { "nonterm", nts } + }}, + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - return true; + return true; } bool RemoteBackend::feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - rapidjson::Value nts; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "feedEnts3", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(parameters, "domain", domain, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "times", ns3prc.d_iterations, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "salt", ns3prc.d_salt.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "narrow", narrow, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - - nts.SetArray(); - for(const auto& t: nonterm) { - rapidjson::Value value(t.first.toString().c_str(), query.GetAllocator()); - nts.PushBack(value, query.GetAllocator()); - } - parameters.AddMember("nonterm", nts, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json::array nts; + + for(const auto& t: nonterm) + nts.push_back(Json::object{ + { "nonterm", t.first.toString() }, + { "auth", t.second } + }); + + Json query = Json::object{ + { "method", "feedEnts3" }, + { "parameters", Json::object{ + { "domain_id", domain_id }, + { "domain", domain.toString() }, + { "times", ns3prc.d_iterations }, + { "salt", ns3prc.d_salt }, + { "narrow", narrow }, + { "trxid", static_cast(d_trxid) }, + { "nonterm", nts } + }}, + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; return true; } bool RemoteBackend::startTransaction(const DNSName& domain, int domain_id) { - rapidjson::Document query,answer; - rapidjson::Value parameters; this->d_trxid = time((time_t*)NULL); - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "startTransaction", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "domain", domain, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "startTransaction" }, + { "parameters", Json::object{ + { "domain", domain.toString() }, + { "domain_id", domain_id }, + { "trxid", static_cast(d_trxid) } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) { d_trxid = -1; return false; @@ -875,122 +785,115 @@ bool RemoteBackend::startTransaction(const DNSName& domain, int domain_id) { return true; } -bool RemoteBackend::commitTransaction() { - rapidjson::Document query,answer; - rapidjson::Value parameters; +bool RemoteBackend::commitTransaction() { + if (d_trxid == -1) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "commitTransaction", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "commitTransaction" }, + { "parameters", Json::object{ + { "trxid", static_cast(d_trxid) } + }} + }; d_trxid = -1; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; return true; } -bool RemoteBackend::abortTransaction() { - rapidjson::Document query,answer; - rapidjson::Value parameters; +bool RemoteBackend::abortTransaction() { + if (d_trxid == -1) return false; - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "abortTransaction", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "abortTransaction" }, + { "parameters", Json::object{ + { "trxid", static_cast(d_trxid) } + }} + }; d_trxid = -1; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; return true; } bool RemoteBackend::calculateSOASerial(const DNSName& domain, const SOAData& sd, time_t& serial) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - rapidjson::Value soadata; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "calculateSOASerial", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER_DNSNAME(parameters, "domain", domain, query.GetAllocator()); - soadata.SetObject(); - JSON_ADD_MEMBER_DNSNAME(soadata, "qname", sd.qname, query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(soadata, "nameserver", sd.nameserver, query.GetAllocator()); - JSON_ADD_MEMBER_DNSNAME(soadata, "hostmaster", sd.hostmaster, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "ttl", sd.ttl, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "serial", sd.serial, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "refresh", sd.refresh, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "retry", sd.retry, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "expire", sd.expire, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "default_ttl", sd.default_ttl, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "domain_id", sd.domain_id, query.GetAllocator()); - JSON_ADD_MEMBER(soadata, "scopeMask", sd.scopeMask, query.GetAllocator()); - parameters.AddMember("sd", soadata, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "calculateSOASerial" }, + { "parameters", Json::object{ + { "domain", domain.toString() }, + { "sd", Json::object{ + { "qname", sd.qname.toString() }, + { "nameserver", sd.nameserver.toString() }, + { "hostmaster", sd.hostmaster.toString() }, + { "ttl", static_cast(sd.ttl) }, + { "serial", static_cast(sd.serial) }, + { "refresh", static_cast(sd.refresh) }, + { "retry", static_cast(sd.retry) }, + { "expire", static_cast(sd.expire) }, + { "default_ttl", static_cast(sd.default_ttl) }, + { "domain_id", static_cast(sd.domain_id) }, + { "scopeMask", sd.scopeMask } + }} + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return false; - serial = getInt64(answer["result"]); + serial = static_cast(doubleFromJson(answer,"result")); return true; } string RemoteBackend::directBackendCmd(const string& querystr) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "directBackendCmd", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "query", querystr.c_str(), query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); + Json query = Json::object{ + { "method", "directBackendCmd" }, + { "parameters", Json::object{ + { "query", querystr } + }} + }; + Json answer; if (this->send(query) == false || this->recv(answer) == false) return "backend command failed"; - return getString(answer["result"]); + return asString(answer["result"]); } bool RemoteBackend::searchRecords(const string &pattern, int maxResults, vector& result) { - rapidjson::Document query,answer; - rapidjson::Value parameters; - - query.SetObject(); - JSON_ADD_MEMBER(query, "method", "searchRecords", query.GetAllocator()); - parameters.SetObject(); - JSON_ADD_MEMBER(parameters, "pattern", pattern.c_str(), query.GetAllocator()); - JSON_ADD_MEMBER(parameters, "maxResults", maxResults, query.GetAllocator()); - query.AddMember("parameters", parameters, query.GetAllocator()); - - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json query = Json::object{ + { "method", "searchRecords" }, + { "parameters", Json::object{ + { "pattern", pattern }, + { "maxResults", maxResults } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - if (answer["result"].IsArray() == false) - return false; + if (answer["result"].is_array() == false) + return false; - for(rapidjson::SizeType i = 0; i < answer["result"].Size(); i++) { - DNSResourceRecord rr; - rapidjson::Value value; - value = ""; - rr.qtype = getString(JSON_GET((*d_result)["result"][d_index], "qtype", value)); - rr.qname = DNSName(getString(JSON_GET((*d_result)["result"][d_index], "qname", value))); - rr.qclass = QClass::IN; - rr.content = getString(JSON_GET((*d_result)["result"][d_index], "content",value)); - value = -1; - rr.ttl = getInt(JSON_GET((*d_result)["result"][d_index], "ttl",value)); - rr.domain_id = getInt(JSON_GET((*d_result)["result"][d_index],"domain_id",value)); - value = 1; - if (d_dnssec) - rr.auth = getInt(JSON_GET((*d_result)["result"][d_index],"auth", value)); - else - rr.auth = 1; - value = 0; - rr.scopeMask = getInt(JSON_GET((*d_result)["result"][d_index],"scopeMask", value)); - result.push_back(rr); + for(const auto& row: answer["result"].array_items()) { + DNSResourceRecord rr; + rr.qtype = stringFromJson(row, "qtype"); + rr.qname = DNSName(stringFromJson(row, "qname")); + rr.qclass = QClass::IN; + rr.content = stringFromJson(row, "content"); + rr.ttl = intFromJson(row, "ttl", 0); + rr.domain_id = intFromJson(row, "domain_id", -1); + if (d_dnssec) + rr.auth = intFromJson(row, "auth", 1); + else + rr.auth = 1; + rr.scopeMask = intFromJson(row, "scopeMask", 0); + result.push_back(rr); } return true; @@ -1002,104 +905,6 @@ bool RemoteBackend::searchComments(const string &pattern, int maxResults, vector return false; } - -// some rapidjson helpers -bool RemoteBackend::getBool(rapidjson::Value &value) { - if (value.IsNull()) return false; - if (value.IsBool()) return value.GetBool(); - if (value.IsInt()) return value.GetInt() != 0; // 0 = false, non-zero true - if (value.IsDouble()) return value.GetDouble() != 0; // 0 = false, non-zero true - if (value.IsString()) { // accepts 0, 1, false, true - std::string tmp = value.GetString(); - if (boost::iequals(tmp, "1") || boost::iequals(tmp, "true")) return true; - if (boost::iequals(tmp, "0") || boost::iequals(tmp, "false")) return false; - } - std::cerr << value.GetType() << endl; - throw PDNSException("Cannot convert rapidjson value into boolean"); -} - -bool Connector::getBool(rapidjson::Value &value) { - if (value.IsNull()) return false; - if (value.IsBool()) return value.GetBool(); - if (value.IsInt()) return value.GetInt() != 0; // 0 = false, non-zero true - if (value.IsDouble()) return value.GetDouble() != 0; // 0 = false, non-zero true - if (value.IsString()) { // accepts 0, 1, false, true - std::string tmp = value.GetString(); - if (boost::iequals(tmp, "1") || boost::iequals(tmp, "true")) return true; - if (boost::iequals(tmp, "0") || boost::iequals(tmp, "false")) return false; - } - - // this is specific for Connector! - return true; -} - -std::string Connector::getString(rapidjson::Value &value) { - if (value.IsString()) return value.GetString(); - if (value.IsBool()) return (value.GetBool() ? "true" : "false"); - if (value.IsInt64()) return std::to_string(value.GetInt64()); - if (value.IsInt()) return std::to_string(value.GetInt()); - if (value.IsDouble()) return std::to_string(value.GetDouble()); - return "(unpresentable value)"; // cannot convert into presentation format -} - -int RemoteBackend::getInt(rapidjson::Value &value) { - if (value.IsInt()) return value.GetInt(); - if (value.IsBool()) return (value.GetBool() ? 1 : 0); - if (value.IsUint()) return static_cast(value.GetUint()); - if (value.IsDouble()) return static_cast(value.GetDouble()); - if (value.IsString()) { // accepts 0, 1, false, true - std::string tmp = value.GetString(); - return std::stoi(tmp); - } - throw PDNSException("Cannot convert rapidjson value into integer"); -} - -unsigned int RemoteBackend::getUInt(rapidjson::Value &value) { - if (value.IsUint()) return value.GetUint(); - if (value.IsBool()) return (value.GetBool() ? 1 : 0); - if (value.IsInt()) return static_cast(value.GetInt()); - if (value.IsDouble()) return static_cast(value.GetDouble()); - if (value.IsString()) { // accepts 0, 1, false, true - std::string tmp = value.GetString(); - return pdns_stou(tmp); - } - throw PDNSException("Cannot convert rapidjson value into integer"); -} - -int64_t RemoteBackend::getInt64(rapidjson::Value &value) { - if (value.IsInt64()) return value.GetInt64(); - if (value.IsBool()) return (value.GetBool() ? 1 : 0); - if (value.IsInt()) return value.GetInt(); - if (value.IsDouble()) return static_cast(value.GetDouble()); - if (value.IsString()) { // accepts 0, 1, false, true - std::string tmp = value.GetString(); - return std::stoll(tmp); - } - throw PDNSException("Cannot convert rapidjson value into integer"); -} - -std::string RemoteBackend::getString(rapidjson::Value &value) { - if (value.IsNull()) return ""; - if (value.IsString()) return value.GetString(); - if (value.IsBool()) return (value.GetBool() ? "true" : "false"); - if (value.IsInt64()) return std::to_string(value.GetInt64()); - if (value.IsInt()) return std::to_string(value.GetInt()); - if (value.IsDouble()) return std::to_string(value.GetDouble()); - throw PDNSException("Cannot convert rapidjson value into std::string"); -} - -double RemoteBackend::getDouble(rapidjson::Value &value) { - if (value.IsDouble()) return value.GetDouble(); - if (value.IsBool()) return (value.GetBool() ? 1.0L : 0.0L); - if (value.IsInt64()) return static_cast(value.GetInt64()); - if (value.IsInt()) return static_cast(value.GetInt()); - if (value.IsString()) { // accepts 0, 1, false, true - std::string tmp = value.GetString(); - return std::stod(tmp); - } - throw PDNSException("Cannot convert rapidjson value into double"); -} - DNSBackend *RemoteBackend::maker() { try { diff --git a/modules/remotebackend/remotebackend.hh b/modules/remotebackend/remotebackend.hh index a7ccefb0c..b3c745f8d 100644 --- a/modules/remotebackend/remotebackend.hh +++ b/modules/remotebackend/remotebackend.hh @@ -1,7 +1,9 @@ #ifndef REMOTEBACKEND_REMOTEBACKEND_HH +#include +#include + #include -#include #include "pdns/arguments.hh" #include "pdns/dns.hh" #include "pdns/dnsbackend.hh" @@ -12,8 +14,8 @@ #include "pdns/sstuff.hh" #include "pdns/ueberbackend.hh" #include "pdns/json.hh" +#include "pdns/lock.hh" #include "yahttp/yahttp.hpp" -#include #ifdef REMOTEBACKEND_ZEROMQ #include @@ -24,20 +26,23 @@ #define zmq_msg_recv(msg, socket, flags) zmq_recv(socket, msg, flags) #endif #endif -#define JSON_GET(obj,val,def) (obj.HasMember(val)?obj["" val ""]:def) -#define JSON_ADD_MEMBER(obj, name, val, alloc) { rapidjson::Value __xval; __xval = val; obj.AddMember(name, __xval, alloc); } -#define JSON_ADD_MEMBER_DNSNAME(obj, name, val, alloc) { rapidjson::Value __xval(val.toString().c_str(), alloc); obj.AddMember(name, __xval, alloc); } + +using json11::Json; class Connector { public: virtual ~Connector() {}; - bool send(rapidjson::Document &value); - bool recv(rapidjson::Document &value); - virtual int send_message(const rapidjson::Document &input) = 0; - virtual int recv_message(rapidjson::Document &output) = 0; + bool send(Json &value); + bool recv(Json &value); + virtual int send_message(const Json &input) = 0; + virtual int recv_message(Json &output) = 0; protected: - bool getBool(rapidjson::Value &value); - std::string getString(rapidjson::Value &value); + string asString(const Json& value) { + if (value.is_number()) return std::to_string(value.int_value()); + if (value.is_bool()) return (value.bool_value()?"1":"0"); + if (value.is_string()) return value.string_value(); + throw JsonException("Json value not convertible to String"); + }; }; // fwd declarations @@ -45,8 +50,8 @@ class UnixsocketConnector: public Connector { public: UnixsocketConnector(std::map options); virtual ~UnixsocketConnector(); - virtual int send_message(const rapidjson::Document &input); - virtual int recv_message(rapidjson::Document &output); + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); private: ssize_t read(std::string &data); ssize_t write(const std::string &data); @@ -64,8 +69,8 @@ class HTTPConnector: public Connector { HTTPConnector(std::map options); ~HTTPConnector(); - virtual int send_message(const rapidjson::Document &input); - virtual int recv_message(rapidjson::Document &output); + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); private: std::string d_url; std::string d_url_suffix; @@ -73,10 +78,10 @@ class HTTPConnector: public Connector { int timeout; bool d_post; bool d_post_json; - bool json2string(const rapidjson::Value &input, std::string &output); - void restful_requestbuilder(const std::string &method, const rapidjson::Value ¶meters, YaHTTP::Request& req); - void post_requestbuilder(const rapidjson::Document &input, YaHTTP::Request& req); - void addUrlComponent(const rapidjson::Value ¶meters, const char *element, std::stringstream& ss); + void restful_requestbuilder(const std::string &method, const Json ¶meters, YaHTTP::Request& req); + void post_requestbuilder(const Json &input, YaHTTP::Request& req); + void addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss); + std::string buildMemberListArgs(std::string prefix, const Json& args); Socket* d_socket; ComboAddress d_addr; }; @@ -86,8 +91,8 @@ class ZeroMQConnector: public Connector { public: ZeroMQConnector(std::map options); virtual ~ZeroMQConnector(); - virtual int send_message(const rapidjson::Document &input); - virtual int recv_message(rapidjson::Document &output); + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); private: void connect(); std::string d_endpoint; @@ -105,8 +110,8 @@ class PipeConnector: public Connector { PipeConnector(std::map options); ~PipeConnector(); - virtual int send_message(const rapidjson::Document &input); - virtual int recv_message(rapidjson::Document &output); + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); private: @@ -169,19 +174,19 @@ class RemoteBackend : public DNSBackend int build(); Connector *connector; bool d_dnssec; - rapidjson::Document *d_result; + Json d_result; int d_index; int64_t d_trxid; std::string d_connstr; - bool getBool(rapidjson::Value &value); - int getInt(rapidjson::Value &value); - unsigned int getUInt(rapidjson::Value &value); - int64_t getInt64(rapidjson::Value &value); - std::string getString(rapidjson::Value &value); - double getDouble(rapidjson::Value &value); - - bool send(rapidjson::Document &value); - bool recv(rapidjson::Document &value); + bool send(Json &value); + bool recv(Json &value); + + string asString(const Json& value) { + if (value.is_number()) return std::to_string(value.int_value()); + if (value.is_bool()) return (value.bool_value()?"1":"0"); + if (value.is_string()) return value.string_value(); + throw JsonException("Json value not convertible to String"); + }; }; #endif diff --git a/modules/remotebackend/unixconnector.cc b/modules/remotebackend/unixconnector.cc index 884102fc6..5c5a7216f 100644 --- a/modules/remotebackend/unixconnector.cc +++ b/modules/remotebackend/unixconnector.cc @@ -2,11 +2,6 @@ #include "config.h" #endif #include "remotebackend.hh" -#include -#include -#include "pdns/lock.hh" -#include -#include #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 108 #endif @@ -33,21 +28,17 @@ UnixsocketConnector::~UnixsocketConnector() { } } -int UnixsocketConnector::send_message(const rapidjson::Document &input) { - rapidjson::StringBuffer output; - rapidjson::Writer w(output); - input.Accept(w); - auto data = std::string(output.GetString(), output.Size()) + "\n"; +int UnixsocketConnector::send_message(const Json& input) { + auto data = input.dump() + "\n"; int rv = this->write(data); if (rv == -1) return -1; return rv; } -int UnixsocketConnector::recv_message(rapidjson::Document &output) { +int UnixsocketConnector::recv_message(Json& output) { int rv,nread; - std::string s_output; - rapidjson::GenericReader , rapidjson::MemoryPoolAllocator<> > r; + std::string s_output,err; struct timeval t0,t; @@ -75,10 +66,9 @@ int UnixsocketConnector::recv_message(rapidjson::Document &output) { if (rv>0) { nread += rv; s_output.append(temp); - rapidjson::StringStream ss(s_output.c_str()); - output.ParseStream<0>(ss); - if (output.HasParseError() == false) - return s_output.size(); + // see if it can be parsed + output = Json::parse(s_output, err); + if (output != nullptr) return s_output.size(); } gettimeofday(&t, NULL); } @@ -133,8 +123,6 @@ ssize_t UnixsocketConnector::write(const std::string &data) { void UnixsocketConnector::reconnect() { struct sockaddr_un sock; - rapidjson::Document init,res; - rapidjson::Value val; int rv; if (connected) return; // no point reconnecting if connected... @@ -163,19 +151,15 @@ void UnixsocketConnector::reconnect() { } // send initialize - init.SetObject(); - val = "initialize"; - init.AddMember("method",val, init.GetAllocator()); - val.SetObject(); - init.AddMember("parameters", val, init.GetAllocator()); + Json::array parameters; + Json msg = Json(Json::object{ + { "method", "initialize" }, + { "parameters", Json(options) }, + }); - for(auto i = options.begin(); i != options.end(); i++) { - val = i->second.c_str(); - init["parameters"].AddMember(i->first.c_str(), val, init.GetAllocator()); - } - - this->send_message(init); - if (this->recv_message(res) == false) { + this->send(msg); + msg = nullptr; + if (this->recv(msg) == false) { L<connected = false; diff --git a/modules/remotebackend/zmqconnector.cc b/modules/remotebackend/zmqconnector.cc index aaa17e869..c810d042e 100644 --- a/modules/remotebackend/zmqconnector.cc +++ b/modules/remotebackend/zmqconnector.cc @@ -4,15 +4,7 @@ #include "remotebackend.hh" #ifdef REMOTEBACKEND_ZEROMQ -#include -#include -#include - -#include - ZeroMQConnector::ZeroMQConnector(std::map options) { - rapidjson::Value val; - rapidjson::Document init,res; int opt=0; // lookup timeout, target and stuff @@ -38,20 +30,15 @@ ZeroMQConnector::ZeroMQConnector(std::map options) { throw PDNSException("Cannot find 'endpoint' option in connection string"); } - init.SetObject(); - val = "initialize"; + Json::array parameters; + Json msg = Json(Json::object{ + { "method", "initialize" }, + { "parameters", Json(options) }, + }); - init.AddMember("method",val, init.GetAllocator()); - val.SetObject(); - init.AddMember("parameters", val, init.GetAllocator()); - - for(auto i = options.begin(); i != options.end(); i++) { - val = i->second.c_str(); - init["parameters"].AddMember(i->first.c_str(), val, init.GetAllocator()); - } - - this->send(init); - if (this->recv(res)==false) { + this->send(msg); + msg = nullptr; + if (this->recv(msg)==false) { L<d_ctx); }; -int ZeroMQConnector::send_message(const rapidjson::Document &input) { - rapidjson::StringBuffer output; - rapidjson::Writer w(output); - input.Accept(w); - auto line = std::string(output.GetString(), output.Size()); +int ZeroMQConnector::send_message(const Json& input) { + auto line = input.dump(); zmq_msg_t message; zmq_msg_init_size(&message, line.size()+1); @@ -96,11 +80,10 @@ int ZeroMQConnector::send_message(const rapidjson::Document &input) { return 0; } -int ZeroMQConnector::recv_message(rapidjson::Document &output) { +int ZeroMQConnector::recv_message(Json& output) { int rv = 0; // try to receive message zmq_pollitem_t item; - rapidjson::GenericReader , rapidjson::MemoryPoolAllocator<> > r; zmq_msg_t message; item.socket = d_sock; @@ -114,25 +97,20 @@ int ZeroMQConnector::recv_message(rapidjson::Document &output) { if (zmq_poll(&item, 1, 1)>0) { // we have an event if ((item.revents & ZMQ_POLLIN) == ZMQ_POLLIN) { - char *data; + string data; size_t msg_size; zmq_msg_init(&message); // read something if(zmq_msg_recv(&message, this->d_sock, ZMQ_NOBLOCK)>0) { + string err; msg_size = zmq_msg_size(&message); - data = new char[msg_size+1]; - memcpy(data, zmq_msg_data(&message), msg_size); - data[msg_size] = '\0'; + data.assign(reinterpret_cast(zmq_msg_data(&message)), msg_size); zmq_msg_close(&message); - - rapidjson::StringStream ss(data); - output.ParseStream<0>(ss); - delete[] data; - - if (output.HasParseError() == false) + output = Json::parse(data, err); + if (output != nullptr) rv = msg_size; else - L<d_endpoint<d_endpoint << ": " << err << endl; break; } else if (errno == EAGAIN) { continue; // try again } } else {