]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Save two pieces of protbuf string in the cache to allow
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 20 Oct 2020 09:11:49 +0000 (11:11 +0200)
committerOtto Moerbeek <otto@drijf.net>
Tue, 10 Nov 2020 08:17:13 +0000 (09:17 +0100)
for mod of the response object.

TODO: NOD stuff, tagging, checking of the taggedOnly flag

pdns/pdns_recursor.cc
pdns/protozero.cc
pdns/protozero.hh
pdns/recpacketcache.cc
pdns/recpacketcache.hh
pdns/test-recpacketcache_cc.cc

index 6b81c3e2de4defe8c901473311efb128ab47c5a6..21464655999b11f46d8483609e62f262d9636093 100644 (file)
@@ -885,8 +885,8 @@ static void protobufLogQuery(uint8_t maskV4, uint8_t maskV6, const boost::uuids:
   Netmask requestorNM(remote, remote.sin4.sin_family == AF_INET ? maskV4 : maskV6);
   ComboAddress requestor = requestorNM.getMaskedNetwork();
   requestor.setPort(remote.getPort());
-  
-  pdns::ProtoZero::Message m{128}; // guess at size
+
+  pdns::ProtoZero::Message m{128, std::string::size_type(policyTags.empty() ? 0 : 64)}; // XXX guesses at sizes
   m.request(uniqueId, requestor, local, qname, qtype, qclass, id, tcp, len);
   m.setServerIdentity(SyncRes::s_serverID);
   m.setEDNSSubnet(ednssubnet, ednssubnet.isIPv4() ? maskV4 : maskV6);
@@ -895,25 +895,24 @@ static void protobufLogQuery(uint8_t maskV4, uint8_t maskV6, const boost::uuids:
   m.setDeviceName(deviceName);
 
   if (!policyTags.empty()) {
-    m.startResponse();
     m.setPolicyTags(policyTags);
-    m.finishResponse();
   }
 
+  std::string msg(m.movebuf());
   for (auto& server : *t_protobufServers) {
-    server->queueData(m.getbuf());
+    server->queueData(msg);
   }
 }
 
-static void protobufLogResponse(const pdns::ProtoZero::Message& message)
+static void protobufLogResponse(pdns::ProtoZero::Message& message)
 {
   if (!t_protobufServers) {
     return;
   }
 
-  string data = message.getbuf();
+  std::string msg(message.movebuf());
   for (auto& server : *t_protobufServers) {
-    server->queueData(data);
+    server->queueData(msg);
   }
 }
 #endif
@@ -1406,15 +1405,14 @@ static void startDoResolve(void *p)
     // Used to tell syncres later on if we should apply NSDNAME and NSIP RPZ triggers for this query
     bool wantsRPZ(true);
     std::unique_ptr<pdns::ProtoZero::Message> pbMessage;
-    std::string::size_type pbUnmutablePart; // defines the (first) part of the protobuf message that is equal for everyone
+    RecursorPacketCache::OptPBData pbDataForCache;
 #ifdef HAVE_PROTOBUF
     if (checkProtobufExport(luaconfsLocal)) {
-      pbMessage = make_unique<pdns::ProtoZero::Message>(128); // guess at size
+      pbMessage = make_unique<pdns::ProtoZero::Message>(128, 128); // XXX guess at sizes
       pbMessage->response(dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
       pbMessage->setServerIdentity(SyncRes::s_serverID);
 
       // RRSets added below
-      pbMessage->startResponse();
     }
 #endif /* HAVE_PROTOBUF */
 
@@ -1871,21 +1869,20 @@ static void startDoResolve(void *p)
       }
       // XXX if (nod) 
       pbMessage->setPolicyTags(dc->d_policyTags);
-      pbMessage->finishResponse();
       pbMessage->setInBytes(packet.size());
 
-      // Done with embedded DNSResponse object and done with unmutable part.
-      pbUnmutablePart = pbMessage->getbuf().length();
+      pbDataForCache = boost::make_optional(RecursorPacketCache::PBData{
+        pbMessage->getmsgbuf(), 
+        pbMessage->getrspbuf(),
+        !appliedPolicy.getName().empty() || !dc->d_policyTags.empty()});
 
-      // Below arte the fields that are not stored in the packet cache and will be appended here and on a cache hit
-      pbMessage->startResponse();
+      // Below are the fields that are not stored in the packet cache and will be appended here and on a cache hit
       if (g_useKernelTimestamp && dc->d_kernelTimestamp.tv_sec) {
         pbMessage->setQueryTime(dc->d_kernelTimestamp.tv_sec, dc->d_kernelTimestamp.tv_usec);
       }
       else {
         pbMessage->setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec);
       }
-      pbMessage->finishResponse();
       pbMessage->setMessageIdentity(dc->d_uuid);
       pbMessage->setSocketFamily(dc->d_source.sin4.sin_family);
       pbMessage->setSocketProtocol(dc->d_tcp);
@@ -1895,7 +1892,6 @@ static void startDoResolve(void *p)
       pbMessage->setTo(dc->d_destination);
       pbMessage->setId(dc->d_mdp.d_header.id);
 
-      // Th exact semantics of timeSec/timeUsec vs queryTimeSec/queryTimeUsec are unclear to me ATM
       pbMessage->setTime();
       pbMessage->setEDNSSubnet(dc->d_ednssubnet.source, dc->d_ednssubnet.source.isIPv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
       pbMessage->setRequestorId(dq.requestorId);
@@ -1955,7 +1951,7 @@ static void startDoResolve(void *p)
                                             pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl :
                                             min(minTTL,SyncRes::s_packetcachettl),
                                             dq.validationState,
-                                            pbMessage.get(), pbUnmutablePart);
+                                            pbDataForCache);
       }
       //      else cerr<<"Not putting in packet cache: "<<sr.wasVariable()<<endl;
     }
@@ -2692,7 +2688,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
     }
 
     bool cacheHit = false;
-    string *pbString = nullptr;
+    RecursorPacketCache::OptPBData pbData{boost::none};
 #ifdef HAVE_PROTOBUF
     if (t_protobufServers) {
       if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) {
@@ -2706,10 +2702,10 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
        as cacheable we would cache it with a wrong tag, so better safe than sorry. */
     vState valState;
     if (qnameParsed) {
-      cacheHit = !SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, qtype, qclass, g_now.tv_sec, &response, &age, &valState, &qhash, &pbString);
+      cacheHit = !SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, qtype, qclass, g_now.tv_sec, &response, &age, &valState, &qhash, &pbData);
     }
     else {
-      cacheHit = !SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, &qtype, &qclass, g_now.tv_sec, &response, &age, &valState, &qhash, &pbString);
+      cacheHit = !SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, &qtype, &qclass, g_now.tv_sec, &response, &age, &valState, &qhash, &pbData);
     }
 
     if (cacheHit) {
@@ -2721,17 +2717,17 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
       }
 
 #ifdef HAVE_PROTOBUF
-      if(t_protobufServers && logResponse /* && !(luaconfsLocal->protobufExportConfig.taggedOnly && pbMessage->appliedPolicyIsSet() && pbMessage->policyTagsAreSet()) */) {
+      if(t_protobufServers && logResponse && !(luaconfsLocal->protobufExportConfig.taggedOnly && pbData && !pbData->d_tagged)) { // XXX
         std::unique_ptr<pdns::ProtoZero::Message> pbMessage;
-        if (pbString != nullptr) {
+        if (pbData) {
           // We take the inmutable string form the cache an are appending a few values
-          pbMessage = make_unique<pdns::ProtoZero::Message>(*pbString, 128); // The extra bytes we are going to add
+          pbMessage = make_unique<pdns::ProtoZero::Message>(pbData->d_message, pbData->d_response, 128, 128); // The extra bytes we are going to add
         } else {
-          pbMessage = make_unique<pdns::ProtoZero::Message>(128);
+          pbMessage = make_unique<pdns::ProtoZero::Message>(128, 128);
           pbMessage->setType(2); // Response
           pbMessage->setServerIdentity(SyncRes::s_serverID);
         }
-        //cerr << "from cache: " << pbMessage->getbuf().length() << endl;
+
         Netmask requestorNM(source, source.sin4.sin_family == AF_INET ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
         ComboAddress requestor = requestorNM.getMaskedNetwork();
         pbMessage->setMessageIdentity(uniqueId);
@@ -2739,23 +2735,20 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
         pbMessage->setTo(destination);
         pbMessage->setSocketProtocol(false);
         pbMessage->setId(dh->id);
-        // Exact semantics of the various timestamps are unclear to me ATM
+
         pbMessage->setTime();
-        pbMessage->startResponse();
         if (g_useKernelTimestamp && tv.tv_sec) {
           pbMessage->setQueryTime(tv.tv_sec, tv.tv_usec);
         }
         else {
           pbMessage->setQueryTime(g_now.tv_sec, g_now.tv_usec);
         }
-        pbMessage->finishResponse();
         pbMessage->setEDNSSubnet(ednssubnet.source, ednssubnet.source.isIPv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
         pbMessage->setRequestorId(requestorId);
         pbMessage->setDeviceId(deviceId);
         pbMessage->setDeviceName(deviceName);
         pbMessage->setFromPort(source.getPort());
         pbMessage->setToPort(destination.getPort());
-        //cerr << "affter adding: " << pbMessage->getbuf().length() << endl;
         protobufLogResponse(*pbMessage);
       }
 #endif /* HAVE_PROTOBUF */
index 2be7f8736cd2f85d4b20ee668b099e7cac8bb9f1..43842e2274ebc99c41752e037cba88b13fd24d48 100644 (file)
 void pdns::ProtoZero::Message::encodeComboAddress(const protozero::pbf_tag_type type, const ComboAddress& ca)
 {
   if (ca.sin4.sin_family == AF_INET) {
-    d_pbf.add_bytes(type, reinterpret_cast<const char*>(&ca.sin4.sin_addr.s_addr), sizeof(ca.sin4.sin_addr.s_addr));
+    d_message.add_bytes(type, reinterpret_cast<const char*>(&ca.sin4.sin_addr.s_addr), sizeof(ca.sin4.sin_addr.s_addr));
   }
   else if (ca.sin4.sin_family == AF_INET6) {
-    d_pbf.add_bytes(type, reinterpret_cast<const char*>(&ca.sin6.sin6_addr.s6_addr), sizeof(ca.sin6.sin6_addr.s6_addr));
+    d_message.add_bytes(type, reinterpret_cast<const char*>(&ca.sin6.sin6_addr.s6_addr), sizeof(ca.sin6.sin6_addr.s6_addr));
   }
 }
 
@@ -40,10 +40,10 @@ void pdns::ProtoZero::Message::encodeNetmask(const protozero::pbf_tag_type type,
     ComboAddress ca(subnet.getNetwork());
     ca.truncate(mask);
     if (ca.sin4.sin_family == AF_INET) {
-      d_pbf.add_bytes(type, reinterpret_cast<const char*>(&ca.sin4.sin_addr.s_addr), sizeof(ca.sin4.sin_addr.s_addr));
+      d_message.add_bytes(type, reinterpret_cast<const char*>(&ca.sin4.sin_addr.s_addr), sizeof(ca.sin4.sin_addr.s_addr));
     }
     else if (ca.sin4.sin_family == AF_INET6) {
-      d_pbf.add_bytes(type, reinterpret_cast<const char*>(&ca.sin6.sin6_addr.s6_addr), sizeof(ca.sin6.sin6_addr.s6_addr));
+      d_message.add_bytes(type, reinterpret_cast<const char*>(&ca.sin6.sin6_addr.s6_addr), sizeof(ca.sin6.sin6_addr.s6_addr));
     }
   }
 }
@@ -94,9 +94,9 @@ void pdns::ProtoZero::Message::addRR(const DNSRecord& record, const std::set<uin
     return;
   }
 
-  protozero::pbf_writer pbf_rr{*d_response, 2};
+  protozero::pbf_writer pbf_rr{d_response, 2};
 
-  encodeDNSName(pbf_rr, d_buffer, 1, record.d_name);
+  encodeDNSName(pbf_rr, d_rspbuf, 1, record.d_name);
   pbf_rr.add_uint32(2, record.d_type);
   pbf_rr.add_uint32(3, record.d_class);
   pbf_rr.add_uint32(4, record.d_ttl);
index 81681acbd246e75649f3564254e4d69208f612dd..7cd15055d987b1e1b4f4848cfeb3d9d1df30769b 100644 (file)
@@ -34,48 +34,69 @@ namespace pdns {
   namespace ProtoZero {
     class Message {
     public:
-      Message(size_t sz) : d_pbf{d_buffer}
+      // Start a new messagebug, constaining separate data for the response part
+      Message(std::string::size_type sz1, std::string::size_type sz2) : d_message{d_msgbuf}, d_response{d_rspbuf}
       {
-        d_buffer.reserve(sz);
+        if (d_msgbuf.capacity() < sz1) {
+          d_msgbuf.reserve(sz1);
+        }
+        if (d_rspbuf.capacity() < sz2) {
+          d_rspbuf.reserve(sz2);
+        }
+      }
+
+      // Construct a Message with (partially) constructed content
+      Message(const std::string& buf1, const std::string& buf2, std::string::size_type sz1, std::string::size_type sz2) :
+        d_msgbuf{buf1}, d_rspbuf{buf2}, d_message{d_msgbuf}, d_response{d_rspbuf}
+      {
+        // We expect to grow the buffer
+        if (d_msgbuf.capacity() - d_msgbuf.length() < sz1) {
+          d_msgbuf.reserve(d_msgbuf.length() + sz1);
+        }
+        if (d_rspbuf.capacity() - d_rspbuf.length() < sz2) {
+          d_msgbuf.reserve(d_rspbuf.length() + sz2);
+        }
       }
-      Message(const std::string& buf, size_t sz) : d_buffer(buf), d_pbf(d_buffer)
+      const std::string& getmsgbuf() const
       {
-        // We expect to grow the buffwer
-        d_buffer.reserve(d_buffer.capacity() + sz);
+        return d_msgbuf;
       }
-      const std::string& getbuf() const
+      const std::string& getrspbuf() const
       {
-        return d_buffer;
+        return d_rspbuf;
       }
       std::string&& movebuf()
       {
-        return std::move(d_buffer);
+        if (!d_rspbuf.empty()) {
+          d_message.add_message(13, d_rspbuf);
+        }
+        return std::move(d_msgbuf);
       }
-      void encodeComboAddress(const protozero::pbf_tag_type type, const ComboAddress& ca);
-      void encodeNetmask(const protozero::pbf_tag_type type, const Netmask& subnet, uint8_t mask);
-      void encodeDNSName(protozero::pbf_writer& pbf, std::string& buffer, const protozero::pbf_tag_type type, const DNSName& name);
+      void encodeComboAddress(protozero::pbf_tag_type type, const ComboAddress& ca);
+      void encodeNetmask(protozero::pbf_tag_type type, const Netmask& subnet, uint8_t mask);
+      void encodeDNSName(protozero::pbf_writer& pbf, std::string& buffer, protozero::pbf_tag_type type, const DNSName& name);
       void request(const boost::uuids::uuid& uniqueId, const ComboAddress& requestor, const ComboAddress& local, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint16_t id, bool tcp, size_t len);
       void response(const DNSName& qname, uint16_t qtype, uint16_t qclass);
 
       void setType(int mtype)
       {
-        d_pbf.add_enum(1, mtype);
+       d_message.add_enum(1, mtype);
       }
       void setMessageIdentity(const boost::uuids::uuid& uniqueId)
       {
-        d_pbf.add_bytes(2, reinterpret_cast<const char*>(uniqueId.begin()), uniqueId.size());
+       d_message.add_bytes(2, reinterpret_cast<const char*>(uniqueId.begin()), uniqueId.size());
       }
       void setServerIdentity(const std::string& serverIdentity)
       {
-        d_pbf.add_bytes(3, serverIdentity.data(), serverIdentity.length());
+       d_message.add_bytes(3, serverIdentity.data(), serverIdentity.length());
       }
       void setSocketFamily(int family)
       {
-        d_pbf.add_enum(4, family == AF_INET ? 1 : 2);
+       d_message.add_enum(4, family == AF_INET ? 1 : 2);
       }
       void setSocketProtocol(bool tcp)
       {
-        d_pbf.add_enum(5, tcp ? 2 : 1);
+       d_message.add_enum(5, tcp ? 2 : 1);
       }
       void setFrom(const ComboAddress& ca)
       {
@@ -88,7 +109,7 @@ namespace pdns {
       void setInBytes(uint64_t len)
       {
         if (len) {
-          d_pbf.add_uint64(8, len);
+         d_message.add_uint64(8, len);
         }
       }
       void setTime()
@@ -96,18 +117,18 @@ namespace pdns {
         struct timespec ts;
         gettime(&ts, true);
         // timeSec
-        d_pbf.add_uint32(9, ts.tv_sec);
+       d_message.add_uint32(9, ts.tv_sec);
         // timeUsec
-        d_pbf.add_uint32(10, ts.tv_nsec / 1000);
+       d_message.add_uint32(10, ts.tv_nsec / 1000);
       }
       void setId(uint16_t id)
       {
-        d_pbf.add_uint32(11, ntohs(id));
+       d_message.add_uint32(11, ntohs(id));
       }
       void setQuestion(const DNSName& qname, uint16_t qtype, uint16_t qclass)
       {
-        protozero::pbf_writer pbf_question{d_pbf, 12};
-        encodeDNSName(pbf_question, d_buffer, 1, qname);
+        protozero::pbf_writer pbf_question{d_message, 12};
+        encodeDNSName(pbf_question, d_msgbuf, 1, qname);
         pbf_question.add_uint32(2, qtype);
         pbf_question.add_uint32(3, qclass);
       }
@@ -117,57 +138,46 @@ namespace pdns {
       }
       void setRequestorId(const std::string& req)
       {
-        if (true || !req.empty()) {
-          d_pbf.add_string(15, req);
+        if (!req.empty()) {
+         d_message.add_string(15, req);
         }
       }
       void setInitialRequesId(const std::string& id)
       {
         if (!id.empty()) {
-          d_pbf.add_string(16, id);
+         d_message.add_string(16, id);
         }
       }
       void setDeviceId(const std::string& id)
       {
-        if (true || !id.empty()) {
-          d_pbf.add_string(17, id);
+        if (!id.empty()) {
+         d_message.add_string(17, id);
         }
       }
       void setNewlyObservedDomain(bool nod)
       {
-        d_pbf.add_bool(18, nod);
+       d_message.add_bool(18, nod);
       }
       void setDeviceName(const std::string& name)
       {
-        if (true || !name.empty()) {
-          d_pbf.add_string(19, name);
+        if (!name.empty()) {
+         d_message.add_string(19, name);
         }
       }
       void setFromPort(in_port_t port)
       {
-        d_pbf.add_uint32(20, port);
+       d_message.add_uint32(20, port);
       }
       void setToPort(in_port_t port)
       {
-        d_pbf.add_uint32(21, port);
+       d_message.add_uint32(21, port);
       }
 
       // DNSResponse related fields below
-      void startResponse()
-      {
-        if (d_response != nullptr) {
-          throw new runtime_error("response already inited");
-        }
-        d_response = new protozero::pbf_writer(d_pbf, 13);
-      }
-      void finishResponse()
-      {
-        delete d_response;
-        d_response = nullptr;
-      }
+
       void setResponseCode(uint8_t rcode)
       {
-        d_response->add_uint32(1, rcode);
+        d_response.add_uint32(1, rcode);
       }
 #ifdef NOD_ENABLED
       void addRR(const DNSRecord& record, const std::set<uint16_t>& exportTypes, bool udr);
@@ -179,16 +189,12 @@ namespace pdns {
       }
       void setAppliedPolicy(const std::string& policy)
       {
-        d_response->add_string(3, policy);
-      }
-      bool appliedPolicyIsSet() const 
-      {
-        return false;
+        d_response.add_string(3, policy);
       }
       void setPolicyTags(const std::unordered_set<std::string>& tags)
       {
         for (const auto& tag : tags) {
-          d_response->add_string(4, tag);
+          d_response.add_string(4, tag);
         }
       }
       void addPolicyTag(const string& tag)
@@ -197,14 +203,10 @@ namespace pdns {
       void removePolicyTag(const string& tag)
       {
       }
-      bool policyTagsAreSet() const
-      {
-        return false;
-      }
       void setQueryTime(uint32_t sec, uint32_t usec)
       {
-        d_response->add_uint32(5, sec);
-        d_response->add_uint32(6, usec);
+        d_response.add_uint32(5, sec);
+        d_response.add_uint32(6, usec);
       }
       void setAppliedPolicyType(const DNSFilterEngine::PolicyType type)
       {
@@ -232,21 +234,22 @@ namespace pdns {
         default:
           throw std::runtime_error("Unsupported protobuf policy type");
         }
-        d_response->add_uint32(7, p);
+        d_response.add_uint32(7, p);
       }
       void setAppliedPolicyTrigger(const DNSName& trigger)
       {
-        encodeDNSName(*d_response, d_buffer, 8, trigger);
+        encodeDNSName(d_response, d_rspbuf, 8, trigger);
       }
       void setAppliedPolicyHit(const std::string& hit)
       {
-        d_response->add_string(9, hit);
+        d_response.add_string(9, hit);
       }
 
     private:
-      std::string d_buffer;
-      protozero::pbf_writer d_pbf;
-      protozero::pbf_writer *d_response{nullptr};
+      std::string d_msgbuf;
+      std::string d_rspbuf;
+      protozero::pbf_writer d_message;
+      protozero::pbf_writer d_response;
     };
   };
 };
index 03758d139277678fb8cca135857f9e51b8800ab0..94c979c50f9aaf19457b7108bff1e4765abf5087 100644 (file)
@@ -50,7 +50,7 @@ bool RecursorPacketCache::qrMatch(const packetCache_t::index<HashTag>::type::ite
   return queryMatches(iter->d_query, queryPacket, qname, optionsToSkip);
 }
 
-bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, std::string** protobufMessage)
+bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata)
 {
   for(auto iter = range.first ; iter != range.second ; ++iter) {
     // the possibility is VERY real that we get hits that are not right - birthday paradox
@@ -72,12 +72,11 @@ bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<Ha
       d_hits++;
       moveCacheItemToBack<SequencedTag>(d_packetCache, iter);
 #ifdef HAVE_PROTOBUF
-      if (protobufMessage) {
-        if (iter->d_protobufMessage) {
-          *protobufMessage = &*iter->d_protobufMessage;
-        }
-        else {
-          *protobufMessage = nullptr;
+      if (pbdata != nullptr) {
+        if (iter->d_pbdata) {
+          *pbdata = iter->d_pbdata;
+        } else {
+          *pbdata = boost::none;
         }
       }
 #endif
@@ -110,7 +109,7 @@ bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string&
 }
 
 bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now,
-                                            std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, std::string** protobufMessage)
+                                            std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata)
 {
   *qhash = canHashPacket(queryPacket, true);
   const auto& idx = d_packetCache.get<HashTag>();
@@ -121,11 +120,11 @@ bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string&
     return false;
   }
 
-  return checkResponseMatches(range, queryPacket, qname, qtype, qclass, now, responsePacket, age, valState, protobufMessage);
+  return checkResponseMatches(range, queryPacket, qname, qtype, qclass, now, responsePacket, age, valState, pbdata);
 }
 
 bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t* qtype, uint16_t* qclass, time_t now,
-                                            std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, std::string** protobufMessage)
+                                            std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData *pbdata)
 {
   *qhash = canHashPacket(queryPacket, true);
   const auto& idx = d_packetCache.get<HashTag>();
@@ -138,11 +137,11 @@ bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string&
 
   qname = DNSName(queryPacket.c_str(), queryPacket.length(), sizeof(dnsheader), false, qtype, qclass, 0);
 
-  return checkResponseMatches(range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, valState, protobufMessage);
+  return checkResponseMatches(range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, valState, pbdata);
 }
 
 
-void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, pdns::ProtoZero::Message* protobufMessage, std::string::size_type pbUnmutablePart)
+void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, const OptPBData& pbdata)
 {
   auto& idx = d_packetCache.get<HashTag>();
   auto range = idx.equal_range(tie(tag,qhash));
@@ -160,11 +159,8 @@ void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash,
     iter->d_creation = now;
     iter->d_vstate = valState;
 #ifdef HAVE_PROTOBUF
-    if (protobufMessage) {
-      std::string s(protobufMessage->movebuf());
-      s.resize(pbUnmutablePart);
-      s.shrink_to_fit();
-      iter->d_protobufMessage = boost::optional<std::string>(s);
+    if (pbdata) {
+      iter->d_pbdata = *pbdata;
     }
 #endif
 
@@ -181,11 +177,8 @@ void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash,
     e.d_tag = tag;
     e.d_vstate = valState;
 #ifdef HAVE_PROTOBUF
-    if (protobufMessage) {
-      std::string s(protobufMessage->movebuf());
-      s.resize(pbUnmutablePart);
-      s.shrink_to_fit();
-      e.d_protobufMessage = boost::optional<std::string>(s);
+    if (pbdata) {
+      e.d_pbdata = *pbdata;
     }
 #endif
     d_packetCache.insert(e);
@@ -225,7 +218,7 @@ uint64_t RecursorPacketCache::doDump(int fd)
   for(auto i=sidx.cbegin(); i != sidx.cend(); ++i) {
     count++;
     try {
-      fprintf(fp.get(), "%s %" PRId64 " %s  ; tag %d pb %zu\n", i->d_name.toString().c_str(), static_cast<int64_t>(i->d_ttd - now), DNSRecordContent::NumberToType(i->d_type).c_str(), i->d_tag, i->d_protobufMessage ? i->d_protobufMessage->length() : 0);
+      fprintf(fp.get(), "%s %" PRId64 " %s  ; tag %d\n", i->d_name.toString().c_str(), static_cast<int64_t>(i->d_ttd - now), DNSRecordContent::NumberToType(i->d_type).c_str(), i->d_tag);
     }
     catch(...) {
       fprintf(fp.get(), "; error printing '%s'\n", i->d_name.empty() ? "EMPTY" : i->d_name.toString().c_str());
index 7faf793fbe7f09e0fe280375e905e8946b30aac9..972e136c0ae329b0a7ad73638b9be3f227ef8c29 100644 (file)
@@ -51,13 +51,20 @@ using namespace ::boost::multi_index;
 class RecursorPacketCache: public PacketCache
 {
 public:
+  struct PBData {
+    std::string d_message;
+    std::string d_response;
+    bool d_tagged;
+  };
+  typedef boost::optional<PBData> OptPBData;
+
   RecursorPacketCache();
   bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash);
   bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash);
-  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, std::string** protobufMessage);
-  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t *qtype, uint16_t* qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, std::string** protobufMessage);
+  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata);
+  bool getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t *qtype, uint16_t* qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata);
   
-  void insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, pdns::ProtoZero::Message* protobufMessage = nullptr, std::string::size_type pbUnmutablePart = 0);
+  void insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, const OptPBData& pbdata);
   void doPruneTo(size_t maxSize=250000);
   uint64_t doDump(int fd);
   int doWipePacketCache(const DNSName& name, uint16_t qtype=0xffff, bool subtree=false);
@@ -80,7 +87,7 @@ private:
     mutable std::string d_packet; // "I know what I am doing"
     mutable std::string d_query;
 #ifdef HAVE_PROTOBUF
-    mutable boost::optional<std::string> d_protobufMessage;
+    mutable OptPBData d_pbdata;
 #endif
     mutable time_t d_ttd;
     mutable time_t d_creation; // so we can 'age' our packets
@@ -110,7 +117,7 @@ private:
   packetCache_t d_packetCache;
 
   static bool qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass);
-  bool checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, std::string** protobufMessage);
+  bool checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata);
 
 public:
   void preRemoval(const Entry& entry)
index 8a4f309a2b0fbf33ee8690f264b506612018eb7c..fce6fcc823a91d78e50ed440bf588bfca7deb282 100644 (file)
@@ -45,16 +45,16 @@ BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple) {
   pw.commit();
   string rpacket((const char*)&packet[0], packet.size());
 
-  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1U);
   rpc.doPruneTo(0);
   BOOST_CHECK_EQUAL(rpc.size(), 0U);
-  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1U);
   rpc.doWipePacketCache(qname);
   BOOST_CHECK_EQUAL(rpc.size(), 0U);
 
-  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1U);
   uint32_t qhash2 = 0;
   bool found = rpc.getResponsePacket(tag, qpacket, time(nullptr), &fpacket, &age, &qhash2);
@@ -140,11 +140,11 @@ BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags) {
   BOOST_CHECK(r1packet != r2packet);
 
   /* inserting a response for tag1 */
-  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1U);
 
   /* inserting a different response for tag2, should not override the first one */
-  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 2U);
 
   /* remove all responses from the cache */
@@ -152,10 +152,10 @@ BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags) {
   BOOST_CHECK_EQUAL(rpc.size(), 0U);
 
   /* reinsert both */
-  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1U);
 
-  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 2U);
 
   /* remove the responses by qname, should remove both */
@@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags) {
   BOOST_CHECK_EQUAL(rpc.size(), 0U);
 
   /* insert the response for tag1 */
-  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1U);
 
   /* we can retrieve it */
@@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags) {
   BOOST_CHECK_EQUAL(temphash, qhash);
 
   /* adding a response for the second tag */
-  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, vState::Indeterminate, nullptr);
+  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, vState::Indeterminate, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 2U);
 
   /* We still get the correct response for the first tag */