for mod of the response object.
TODO: NOD stuff, tagging, checking of the taggedOnly flag
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);
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
// 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 */
}
// 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);
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);
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;
}
}
bool cacheHit = false;
- string *pbString = nullptr;
+ RecursorPacketCache::OptPBData pbData{boost::none};
#ifdef HAVE_PROTOBUF
if (t_protobufServers) {
if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) {
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) {
}
#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);
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 */
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));
}
}
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));
}
}
}
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);
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)
{
void setInBytes(uint64_t len)
{
if (len) {
- d_pbf.add_uint64(8, len);
+ d_message.add_uint64(8, len);
}
}
void setTime()
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);
}
}
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);
}
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)
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)
{
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;
};
};
};
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
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
}
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>();
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>();
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));
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
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);
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());
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);
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
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)
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);
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 */
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 */
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 */
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 */