]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/communicator.cc
Merge pull request #8223 from PowerDNS/omoerbeek-patch-1
[thirdparty/pdns.git] / pdns / communicator.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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "packetcache.hh"
26 #include "utility.hh"
27 #include <errno.h>
28 #include "communicator.hh"
29 #include <set>
30 #include <boost/utility.hpp>
31 #include "dnsbackend.hh"
32 #include "ueberbackend.hh"
33 #include "packethandler.hh"
34 #include "resolver.hh"
35 #include "logger.hh"
36 #include "dns.hh"
37 #include "arguments.hh"
38 #include "packetcache.hh"
39 #include "threadname.hh"
40
41 // there can be MANY OF THESE
42 void CommunicatorClass::retrievalLoopThread(void)
43 {
44 setThreadName("pdns/comm-retre");
45 for(;;) {
46 d_suck_sem.wait();
47 SuckRequest sr;
48 {
49 Lock l(&d_lock);
50 if(d_suckdomains.empty())
51 continue;
52
53 sr=d_suckdomains.front();
54 d_suckdomains.pop_front();
55 }
56 suck(sr.domain, sr.master);
57 }
58 }
59
60 void CommunicatorClass::loadArgsIntoSet(const char *listname, set<string> &listset)
61 {
62 vector<string> parts;
63 stringtok(parts, ::arg()[listname], ", \t");
64 for (vector<string>::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) {
65 try {
66 ComboAddress caIp(*iter, 53);
67 listset.insert(caIp.toStringWithPort());
68 }
69 catch(PDNSException &e) {
70 g_log<<Logger::Error<<"Unparseable IP in "<<listname<<". Error: "<<e.reason<<endl;
71 _exit(1);
72 }
73 }
74 }
75
76 void CommunicatorClass::go()
77 {
78 try {
79 PacketHandler::s_allowNotifyFrom.toMasks(::arg()["allow-notify-from"] );
80 }
81 catch(PDNSException &e) {
82 g_log<<Logger::Error<<"Unparseable IP in allow-notify-from. Error: "<<e.reason<<endl;
83 _exit(1);
84 }
85
86 pthread_t tid;
87 pthread_create(&tid,0,&launchhelper,this); // Starts CommunicatorClass::mainloop()
88 for(int n=0; n < ::arg().asNum("retrieval-threads", 1); ++n)
89 pthread_create(&tid, 0, &retrieveLaunchhelper, this); // Starts CommunicatorClass::retrievalLoopThread()
90
91 d_preventSelfNotification = ::arg().mustDo("prevent-self-notification");
92
93 try {
94 d_onlyNotify.toMasks(::arg()["only-notify"]);
95 }
96 catch(PDNSException &e) {
97 g_log<<Logger::Error<<"Unparseable IP in only-notify. Error: "<<e.reason<<endl;
98 _exit(1);
99 }
100
101 loadArgsIntoSet("also-notify", d_alsoNotify);
102
103 loadArgsIntoSet("forward-notify", PacketHandler::s_forwardNotify);
104 }
105
106 void CommunicatorClass::mainloop(void)
107 {
108 try {
109 setThreadName("pdns/comm-main");
110 signal(SIGPIPE,SIG_IGN);
111 g_log<<Logger::Error<<"Master/slave communicator launching"<<endl;
112 PacketHandler P;
113 d_tickinterval=::arg().asNum("slave-cycle-interval");
114 makeNotifySockets();
115
116 int rc;
117 time_t next, tick;
118
119 for(;;) {
120 slaveRefresh(&P);
121 masterUpdateCheck(&P);
122 tick=doNotifications(); // this processes any notification acknowledgements and actually send out our own notifications
123
124 tick = min (tick, d_tickinterval);
125
126 next=time(0)+tick;
127
128 while(time(0) < next) {
129 rc=d_any_sem.tryWait();
130
131 if(rc) {
132 bool extraSlaveRefresh = false;
133 Utility::sleep(1);
134 {
135 Lock l(&d_lock);
136 if (d_tocheck.size())
137 extraSlaveRefresh = true;
138 }
139 if (extraSlaveRefresh)
140 slaveRefresh(&P);
141 }
142 else {
143 // eat up extra posts to avoid busy looping if many posts were done
144 while (d_any_sem.tryWait() == 0) {
145 }
146 break; // something happened
147 }
148 // this gets executed at least once every second
149 doNotifications();
150 }
151 }
152 }
153 catch(PDNSException &ae) {
154 g_log<<Logger::Error<<"Exiting because communicator thread died with error: "<<ae.reason<<endl;
155 Utility::sleep(1);
156 _exit(1);
157 }
158 catch(std::exception &e) {
159 g_log<<Logger::Error<<"Exiting because communicator thread died with STL error: "<<e.what()<<endl;
160 _exit(1);
161 }
162 catch( ... )
163 {
164 g_log << Logger::Error << "Exiting because communicator caught unknown exception." << endl;
165 _exit(1);
166 }
167 }
168