From: Remi Gacogne Date: Tue, 21 Sep 2021 15:14:03 +0000 (+0200) Subject: auth: Speedup DNSRecordContent::deserialize() a little X-Git-Tag: dnsdist-1.8.0-rc1~72^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F11511%2Fhead;p=thirdparty%2Fpdns.git auth: Speedup DNSRecordContent::deserialize() a little The move from a vector to a PacketBuffer prevents the memory from being zeroed while we are going to overwrite it right away. The change from MOADNSParser to PacketReader avoids the need to copy the header and the whole packet (allocation + copy), parse the qname again, as well as the allocation of a vector of records while we know we have only one of these. --- diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc index 9a2ee1a599..fac2dbdda5 100644 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@ -25,6 +25,7 @@ #include #include "namespaces.hh" +#include "noinitvector.hh" UnknownRecordContent::UnknownRecordContent(const string& zone) { @@ -84,16 +85,12 @@ shared_ptr DNSRecordContent::deserialize(const DNSName& qname, dnsheader.qdcount=htons(1); dnsheader.ancount=htons(1); - vector packet; // build pseudo packet - + PacketBuffer packet; // build pseudo packet /* will look like: dnsheader, 5 bytes, encoded qname, dns record header, serialized data */ - const auto& encoded = qname.getStorage(); - packet.resize(sizeof(dnsheader) + 5 + encoded.size() + sizeof(struct dnsrecordheader) + serialized.size()); uint16_t pos=0; - memcpy(&packet[0], &dnsheader, sizeof(dnsheader)); pos+=sizeof(dnsheader); constexpr std::array tmp= {'\x0', '\x0', '\x1', '\x0', '\x1' }; // root question for ns_t_a @@ -114,9 +111,16 @@ shared_ptr DNSRecordContent::deserialize(const DNSName& qname, (void) pos; } - MOADNSParser mdp(false, reinterpret_cast(packet.data()), packet.size()); - shared_ptr ret= mdp.d_answers.begin()->first.d_content; - return ret; + DNSRecord dr; + dr.d_class = QClass::IN; + dr.d_type = qtype; + dr.d_name = qname; + dr.d_clen = serialized.size(); + PacketReader pr(pdns_string_view(reinterpret_cast(packet.data()), packet.size()), packet.size() - serialized.size() - sizeof(dnsrecordheader)); + /* needed to get the record boundaries right */ + pr.getDnsrecordheader(drh); + auto content = DNSRecordContent::mastermake(dr, pr, Opcode::Query); + return content; } std::shared_ptr DNSRecordContent::mastermake(const DNSRecord &dr, diff --git a/pdns/dnsparser.hh b/pdns/dnsparser.hh index 0ac1903be0..98f7910581 100644 --- a/pdns/dnsparser.hh +++ b/pdns/dnsparser.hh @@ -200,7 +200,8 @@ public: virtual std::string getZoneRepresentation(bool noDot=false) const = 0; virtual ~DNSRecordContent() {} virtual void toPacket(DNSPacketWriter& pw)=0; - virtual string serialize(const DNSName& qname, bool canonic=false, bool lowerCase=false) // it would rock if this were const, but it is too hard + // returns the wire format of the content, possibly including compressed pointers pointing to the owner name (unless canonic or lowerCase are set) + virtual string serialize(const DNSName& qname, bool canonic=false, bool lowerCase=false) // it would rock if this were const, but it is too hard because we use the same method (xfrPacket) for both kinds of conversion (fromPacket, toPacket) { vector packet; DNSPacketWriter pw(packet, g_rootdnsname, 1); @@ -223,6 +224,7 @@ public: return typeid(*this)==typeid(rhs) && this->getZoneRepresentation() == rhs.getZoneRepresentation(); } + // parse the content in wire format, possibly including compressed pointers pointing to the owner name static shared_ptr deserialize(const DNSName& qname, uint16_t qtype, const string& serialized); void doRecordCheck(const struct DNSRecord&){}