File: nod.hh

package info (click to toggle)
pdns-recursor 4.8.8-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,620 kB
  • sloc: cpp: 95,714; javascript: 20,651; sh: 4,679; makefile: 652; xml: 37
file content (121 lines) | stat: -rw-r--r-- 5,409 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
/*
 * This file is part of PowerDNS or dnsdist.
 * Copyright -- PowerDNS.COM B.V. and its contributors
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * In addition, for the avoidance of any doubt, permission is granted to
 * link this program with OpenSSL and to (re)distribute the binaries
 * produced as the result of such linking.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#pragma once
#include <atomic>
#include <mutex>
#include <thread>
#include <boost/filesystem.hpp>
#include "dnsname.hh"
#include "lock.hh"
#include "stable-bloom.hh"

namespace nod {
  const float c_fp_rate = 0.01;
  const size_t c_num_cells = 67108864;
  const uint8_t c_num_dec = 10;
  const unsigned int snapshot_interval_default = 600;
  const std::string bf_suffix = "bf";
  const std::string sbf_prefix = "sbf";

  // Theses classes are not designed to be shared between threads
  // Use a new instance per-thread, e.g. using thread local storage
  // Synchronization (at the class level) is still needed for reading from
  // and writing to the cache dir
  // Synchronization (at the instance level) is needed when snapshotting
  class PersistentSBF {
  public:
    PersistentSBF() : d_sbf(bf::stableBF(c_fp_rate, c_num_cells, c_num_dec)) {}
    PersistentSBF(uint32_t num_cells) : d_sbf(bf::stableBF(c_fp_rate, num_cells, c_num_dec)) {}
    bool init(bool ignore_pid=false);
    void setPrefix(const std::string& prefix) { d_prefix = prefix; } // Added to filenames in cachedir
    void setCacheDir(const std::string& cachedir);
    bool snapshotCurrent(std::thread::id tid); // Write the current file out to disk
    void add(const std::string& data) { 
      // The only time this should block is when snapshotting
      d_sbf.lock()->add(data);
    }
    bool test(const std::string& data) { return d_sbf.lock()->test(data); }
    bool testAndAdd(const std::string& data) { 
      // The only time this should block is when snapshotting
      return d_sbf.lock()->testAndAdd(data);
    }
  private:
    void remove_tmp_files(const boost::filesystem::path&, std::lock_guard<std::mutex>&);

    bool d_init{false};
    LockGuarded<bf::stableBF> d_sbf; // Stable Bloom Filter
    std::string d_cachedir;
    std::string d_prefix = sbf_prefix;
    static std::mutex d_cachedir_mutex; // One mutex for all instances of this class
  };

  class NODDB {
  public:
    NODDB() : d_psbf{} {}
    NODDB(uint32_t num_cells) : d_psbf{num_cells} {}
    // Set ignore_pid to true if you don't mind loading files
    // created by the current process
    bool init(bool ignore_pid=false) { 
      d_psbf.setPrefix("nod");
      return d_psbf.init(ignore_pid); 
    }
    bool isNewDomain(const std::string& domain); // Returns true if newly observed domain
    bool isNewDomain(const DNSName& dname); // As above
    bool isNewDomainWithParent(const std::string& domain, std::string& observed); // Returns true if newly observed domain, in which case "observed" contains the parent domain which *was* observed (or "" if domain is . or no parent domains observed)
    bool isNewDomainWithParent(const DNSName& dname, std::string& observed); // As above
    void addDomain(const DNSName& dname); // You need to add this to refresh frequently used domains
    void addDomain(const std::string& domain); // As above
    void setSnapshotInterval(unsigned int secs) { d_snapshot_interval = secs; }
    void setCacheDir(const std::string& cachedir) { d_psbf.setCacheDir(cachedir); }
    bool snapshotCurrent(std::thread::id tid) { return d_psbf.snapshotCurrent(tid); }
    static void startHousekeepingThread(std::shared_ptr<NODDB> noddbp, std::thread::id tid) {
      noddbp->housekeepingThread(tid);
    }
  private:
    PersistentSBF d_psbf;
    unsigned int d_snapshot_interval{snapshot_interval_default}; // Number seconds between snapshots    
    void housekeepingThread(std::thread::id tid);
  };

  class UniqueResponseDB {
  public:
    UniqueResponseDB() : d_psbf{} {}
    UniqueResponseDB(uint32_t num_cells) : d_psbf{num_cells} {}
    bool init(bool ignore_pid=false) {
      d_psbf.setPrefix("udr");
      return d_psbf.init(ignore_pid); 
    }
    bool isUniqueResponse(const std::string& response);
    void addResponse(const std::string& response);
    void setSnapshotInterval(unsigned int secs) { d_snapshot_interval = secs; }
    void setCacheDir(const std::string& cachedir) { d_psbf.setCacheDir(cachedir); }
    bool snapshotCurrent(std::thread::id tid) { return d_psbf.snapshotCurrent(tid); }
    static void startHousekeepingThread(std::shared_ptr<UniqueResponseDB> udrdbp, std::thread::id tid) {
      udrdbp->housekeepingThread(tid);
    }
  private:
    PersistentSBF d_psbf;
    unsigned int d_snapshot_interval{snapshot_interval_default}; // Number seconds between snapshots    
    void housekeepingThread(std::thread::id tid); 
  };

}