File: recpacketcache.cc

package info (click to toggle)
pdns-recursor 3.7.3-1~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 1,516 kB
  • sloc: cpp: 25,908; ansic: 1,938; sh: 592; makefile: 137
file content (122 lines) | stat: -rw-r--r-- 3,076 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <boost/foreach.hpp>
#include "recpacketcache.hh"
#include "cachecleaner.hh"
#include "dns.hh"
#include "namespaces.hh"
#include "lock.hh"
#include "dnswriter.hh"

RecursorPacketCache::RecursorPacketCache()
{
  d_hits = d_misses = 0;
}

int RecursorPacketCache::doWipePacketCache(const string& name, uint16_t qtype)
{
  vector<uint8_t> packet;
  DNSPacketWriter pw(packet, toLower(name), 0);
  pw.getHeader()->rd=1;
  Entry e;
  e.d_packet.assign((const char*)&*packet.begin(), packet.size());

  // so the idea is, we search for a packet with qtype=0, which is ahead of anything with that name

  int count=0;
  for(packetCache_t::iterator iter = d_packetCache.lower_bound(e); iter != d_packetCache.end(); ) {
    const struct dnsheader* packet = reinterpret_cast<const struct dnsheader*>((*iter).d_packet.c_str());
    if(packet->qdcount==0)
      break;
    uint16_t t;
    string found=questionExpand(iter->d_packet.c_str(), iter->d_packet.length(), t);
    if(!pdns_iequals(found, name)) {  
      break;
    }
    if(t==qtype || qtype==0xffff) {
      iter=d_packetCache.erase(iter);
      count++;
    }
    else
      ++iter;
  }
  return count;
}

bool RecursorPacketCache::getResponsePacket(const std::string& queryPacket, time_t now, 
  std::string* responsePacket, uint32_t* age)
{
  struct Entry e;
  e.d_packet=queryPacket;
  
  packetCache_t::const_iterator iter = d_packetCache.find(e);
  
  if(iter == d_packetCache.end()) {
    d_misses++;
    return false;
  }
    
  if((uint32_t)now < iter->d_ttd) { // it is fresh!
//    cerr<<"Fresh for another "<<iter->d_ttd - now<<" seconds!"<<endl;
    *age = now - iter->d_creation;
    uint16_t id;
    memcpy(&id, queryPacket.c_str(), 2); 
    *responsePacket = iter->d_packet;
    responsePacket->replace(0, 2, (char*)&id, 2);
    
    string::size_type i=sizeof(dnsheader);

    for(;;) {
      int labellen = (unsigned char)queryPacket[i];
      if(!labellen || i + labellen > responsePacket->size()) break;
      i++;
      responsePacket->replace(i, labellen, queryPacket, i, labellen);
      i = i + labellen;
    }

    d_hits++;
    moveCacheItemToBack(d_packetCache, iter);

    return true;
  }
  moveCacheItemToFront(d_packetCache, iter);
  d_misses++;
  return false;
}

void RecursorPacketCache::insertResponsePacket(const std::string& responsePacket, time_t now, uint32_t ttl)
{
  struct Entry e;
  e.d_packet = responsePacket;
  e.d_ttd = now+ttl;
  e.d_creation = now;
  packetCache_t::iterator iter = d_packetCache.find(e);
  
  if(iter != d_packetCache.end()) {
    iter->d_packet = responsePacket;
    iter->d_ttd = now + ttl;
    iter->d_creation = now;
  }
  else 
    d_packetCache.insert(e);
}

uint64_t RecursorPacketCache::size()
{
  return d_packetCache.size();
}

uint64_t RecursorPacketCache::bytes()
{
  uint64_t sum=0;
  BOOST_FOREACH(const struct Entry& e, d_packetCache) {
    sum += sizeof(e) + e.d_packet.length() + 4;
  }
  return sum;
}


void RecursorPacketCache::doPruneTo(unsigned int maxCached)
{
  pruneCollection(d_packetCache, maxCached);
}