]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/communicator.hh
Initial revision
[thirdparty/pdns.git] / pdns / communicator.hh
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 #ifndef PDNS_COMMUNICATOR_HH
20 #define PDNS_COMMUNICATOR_HH
21
22 #include <pthread.h>
23 #include <string>
24 #include <semaphore.h>
25 #include <queue>
26 #include <list>
27
28 #ifndef WIN32
29 # include <unistd.h>
30 # include <fcntl.h>
31 # include <netdb.h>
32 #endif // WIN32
33
34 #include "lock.hh"
35 #include "packethandler.hh"
36
37 using namespace std;
38
39 struct SuckRequest
40 {
41 string domain;
42 string master;
43 };
44
45 class NotificationQueue
46 {
47 public:
48 void add(const string &domain, const string &ip)
49 {
50 NotificationRequest nr;
51 nr.domain = domain;
52 nr.ip = ip;
53 nr.attempts = 0;
54 nr.id = Utility::random()%0xffff;
55 nr.next = time(0);
56
57 d_nqueue.push_back(nr);
58 }
59
60 bool removeIf(const string &remote, u_int16_t id, const string &domain)
61 {
62 for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) {
63 cout<<i->id<<" "<<id<<endl;
64 cout<<i->ip<<" "<<remote<<endl;
65 cout<<i->domain<<" "<<domain<<endl;
66
67 if(i->id==id && i->ip==remote && i->domain==domain) {
68 d_nqueue.erase(i);
69 return true;
70 }
71 }
72 return false;
73 }
74
75 bool getOne(string &domain, string &ip, u_int16_t *id, bool &purged)
76 {
77 for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i)
78 if(i->next <= time(0)) {
79 i->attempts++;
80 purged=false;
81 i->next=time(0)+1+(1<<i->attempts);
82 domain=i->domain;
83 ip=i->ip;
84 *id=i->id;
85 purged=false;
86 if(i->attempts>4) {
87 purged=true;
88 d_nqueue.erase(i);
89 }
90 return true;
91 }
92 return false;
93 }
94
95 time_t earliest()
96 {
97 time_t early=1<<31-1; // y2038 problem lurking here :-)
98 for(d_nqueue_t::const_iterator i=d_nqueue.begin();i!=d_nqueue.end();++i)
99 early=min(early,i->next);
100 return early-time(0);
101 }
102
103 private:
104 struct NotificationRequest
105 {
106 string domain;
107 string ip;
108 int attempts;
109 u_int16_t id;
110 time_t next;
111 };
112
113 typedef list<NotificationRequest>d_nqueue_t;
114 d_nqueue_t d_nqueue;
115
116 };
117
118 /** this class contains a thread that communicates with other nameserver and does housekeeping.
119 Initially, it is notified only of zones that need to be pulled in because they have been updated. */
120
121 class CommunicatorClass
122 {
123 public:
124 CommunicatorClass()
125 {
126 pthread_mutex_init(&d_lock,0);
127 pthread_mutex_init(&d_holelock,0);
128 // sem_init(&d_suck_sem,0,0);
129 // sem_init(&d_any_sem,0,0);
130 d_tickinterval=60;
131 }
132 int doNotifications();
133 void go()
134 {
135 pthread_t tid;
136 pthread_create(&tid,0,&launchhelper,this);
137 }
138
139 void drillHole(const string &domain, const string &ip);
140 bool justNotified(const string &domain, const string &ip);
141 void addSuckRequest(const string &domain, const string &master);
142 void notify(const string &domain, const string &ip);
143 void mainloop();
144 static void *launchhelper(void *p)
145 {
146 static_cast<CommunicatorClass *>(p)->mainloop();
147 return 0;
148 }
149 bool notifyDomain(const string &domain);
150 private:
151 void makeNotifySocket();
152 void queueNotifyDomain(const string &domain, DNSBackend *B);
153 int d_nsock;
154 map<pair<string,string>,time_t>d_holes;
155 pthread_mutex_t d_holelock;
156 void suck(const string &domain, const string &remote);
157 void slaveRefresh(PacketHandler *P);
158 void masterUpdateCheck(PacketHandler *P);
159 pthread_mutex_t d_lock;
160 queue<SuckRequest> d_suckdomains;
161 Semaphore d_suck_sem;
162 Semaphore d_any_sem;
163 int d_tickinterval;
164 NotificationQueue d_nq;
165 };
166
167 #endif