]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/rec-tcpout.cc
Merge pull request #13387 from omoerbeek/rec-b-root-servers
[thirdparty/pdns.git] / pdns / recursordist / rec-tcpout.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include "rec-tcpout.hh"
24
25 // This line from /usr/include/openssl/ssl2.h: # define CERT char
26 // throws dnsrecords.hh off the rails.
27 #undef CERT
28
29 #include "syncres.hh"
30
31 timeval TCPOutConnectionManager::s_maxIdleTime;
32 size_t TCPOutConnectionManager::s_maxQueries;
33 size_t TCPOutConnectionManager::s_maxIdlePerAuth;
34 size_t TCPOutConnectionManager::s_maxIdlePerThread;
35
36 void TCPOutConnectionManager::cleanup(const struct timeval& now)
37 {
38 if (s_maxIdleTime.tv_sec == 0 && s_maxIdleTime.tv_usec == 0) {
39 // no maximum idle time
40 return;
41 }
42
43 for (auto it = d_idle_connections.begin(); it != d_idle_connections.end();) {
44 timeval idle = now - it->second.d_last_used;
45 if (s_maxIdleTime < idle) {
46 it = d_idle_connections.erase(it);
47 }
48 else {
49 ++it;
50 }
51 }
52 }
53
54 void TCPOutConnectionManager::store(const struct timeval& now, const ComboAddress& ip, Connection&& connection)
55 {
56 ++connection.d_numqueries;
57 if (s_maxQueries > 0 && connection.d_numqueries >= s_maxQueries) {
58 return;
59 }
60
61 if (d_idle_connections.size() >= s_maxIdlePerThread || d_idle_connections.count(ip) >= s_maxIdlePerAuth) {
62 cleanup(now);
63 }
64
65 if (d_idle_connections.size() >= s_maxIdlePerThread) {
66 return;
67 }
68 if (d_idle_connections.count(ip) >= s_maxIdlePerAuth) {
69 return;
70 }
71
72 gettimeofday(&connection.d_last_used, nullptr);
73 d_idle_connections.emplace(ip, std::move(connection));
74 }
75
76 TCPOutConnectionManager::Connection TCPOutConnectionManager::get(const ComboAddress& ip)
77 {
78 if (d_idle_connections.count(ip) > 0) {
79 auto h = d_idle_connections.extract(ip);
80 return h.mapped();
81 }
82 return Connection{};
83 }
84
85 uint64_t getCurrentIdleTCPConnections()
86 {
87 return broadcastAccFunction<uint64_t>([] { return t_tcp_manager.getSize(); });
88 }