]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth: Speedup DNSRecordContent::deserialize() a little 11511/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 21 Sep 2021 15:14:03 +0000 (17:14 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 23 Jan 2023 09:44:06 +0000 (10:44 +0100)
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.

pdns/dnsparser.cc
pdns/dnsparser.hh

index 9a2ee1a5994960be7bded2b3020c1e467a197c9d..fac2dbdda5aa017a67650af6e64bfa91b5f625bd 100644 (file)
@@ -25,6 +25,7 @@
 #include <boost/format.hpp>
 
 #include "namespaces.hh"
+#include "noinitvector.hh"
 
 UnknownRecordContent::UnknownRecordContent(const string& zone)
 {
@@ -84,16 +85,12 @@ shared_ptr<DNSRecordContent> DNSRecordContent::deserialize(const DNSName& qname,
   dnsheader.qdcount=htons(1);
   dnsheader.ancount=htons(1);
 
-  vector<uint8_t> 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<uint8_t, 5> tmp= {'\x0', '\x0', '\x1', '\x0', '\x1' }; // root question for ns_t_a
@@ -114,9 +111,16 @@ shared_ptr<DNSRecordContent> DNSRecordContent::deserialize(const DNSName& qname,
     (void) pos;
   }
 
-  MOADNSParser mdp(false, reinterpret_cast<const char *>(packet.data()), packet.size());
-  shared_ptr<DNSRecordContent> 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<const char*>(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> DNSRecordContent::mastermake(const DNSRecord &dr,
index 0ac1903be0cd84893a890f0b42e477956c311e94..98f791058129e5f03d0dc9e2eab20cbf2271db10 100644 (file)
@@ -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<uint8_t> 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<DNSRecordContent> deserialize(const DNSName& qname, uint16_t qtype, const string& serialized);
 
   void doRecordCheck(const struct DNSRecord&){}