aboutsummaryrefslogtreecommitdiff
path: root/src/zonemaster
diff options
context:
space:
mode:
Diffstat (limited to 'src/zonemaster')
-rw-r--r--src/zonemaster/.gitignore1
-rw-r--r--src/zonemaster/Makefile.am17
-rw-r--r--src/zonemaster/gnunet-service-zonemaster-monitor.c477
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c302
-rw-r--r--src/zonemaster/zonemaster.conf.in21
5 files changed, 556 insertions, 262 deletions
diff --git a/src/zonemaster/.gitignore b/src/zonemaster/.gitignore
index 1a0e22b66..cde57fa0a 100644
--- a/src/zonemaster/.gitignore
+++ b/src/zonemaster/.gitignore
@@ -1 +1,2 @@
1gnunet-service-zonemaster 1gnunet-service-zonemaster
2gnunet-service-zonemaster-monitor
diff --git a/src/zonemaster/Makefile.am b/src/zonemaster/Makefile.am
index 21f986498..b655b9ef3 100644
--- a/src/zonemaster/Makefile.am
+++ b/src/zonemaster/Makefile.am
@@ -1,5 +1,5 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4plugindir = $(libdir)/gnunet 4plugindir = $(libdir)/gnunet
5 5
@@ -20,11 +20,11 @@ if USE_COVERAGE
20endif 20endif
21 21
22libexec_PROGRAMS = \ 22libexec_PROGRAMS = \
23 gnunet-service-zonemaster 23 gnunet-service-zonemaster \
24 gnunet-service-zonemaster-monitor
24 25
25gnunet_service_zonemaster_SOURCES = \ 26gnunet_service_zonemaster_SOURCES = \
26 gnunet-service-zonemaster.c 27 gnunet-service-zonemaster.c
27
28gnunet_service_zonemaster_LDADD = \ 28gnunet_service_zonemaster_LDADD = \
29 $(top_builddir)/src/dht/libgnunetdht.la \ 29 $(top_builddir)/src/dht/libgnunetdht.la \
30 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 30 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -33,3 +33,14 @@ gnunet_service_zonemaster_LDADD = \
33 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 33 $(top_builddir)/src/namestore/libgnunetnamestore.la \
34 $(GN_LIBINTL) 34 $(GN_LIBINTL)
35 35
36
37gnunet_service_zonemaster_monitor_SOURCES = \
38 gnunet-service-zonemaster-monitor.c
39
40gnunet_service_zonemaster_monitor_LDADD = \
41 $(top_builddir)/src/dht/libgnunetdht.la \
42 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
43 $(top_builddir)/src/statistics/libgnunetstatistics.la \
44 $(top_builddir)/src/util/libgnunetutil.la \
45 $(top_builddir)/src/namestore/libgnunetnamestore.la \
46 $(GN_LIBINTL)
diff --git a/src/zonemaster/gnunet-service-zonemaster-monitor.c b/src/zonemaster/gnunet-service-zonemaster-monitor.c
new file mode 100644
index 000000000..9a6fa678e
--- /dev/null
+++ b/src/zonemaster/gnunet-service-zonemaster-monitor.c
@@ -0,0 +1,477 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2017, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file zonemaster/gnunet-service-zonemaster-monitor.c
21 * @brief monitor namestore changes and publish them immediately to GNUnet name system
22 * @author Christian Grothoff
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_dht_service.h"
27#include "gnunet_namestore_service.h"
28#include "gnunet_statistics_service.h"
29
30
31#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
32
33
34/**
35 * How often should we (re)publish each record before
36 * it expires?
37 */
38#define PUBLISH_OPS_PER_EXPIRATION 4
39
40/**
41 * How many pending DHT operations do we allow at most?
42 */
43#define DHT_QUEUE_LIMIT 2000
44
45/**
46 * How many events may the namestore give us before it has to wait
47 * for us to keep up?
48 */
49#define NAMESTORE_QUEUE_LIMIT 5
50
51/**
52 * What replication level do we use for DHT PUT operations?
53 */
54#define DHT_GNS_REPLICATION_LEVEL 5
55
56
57/**
58 * Handle for DHT PUT activity triggered from the namestore monitor.
59 */
60struct DhtPutActivity
61{
62 /**
63 * Kept in a DLL.
64 */
65 struct DhtPutActivity *next;
66
67 /**
68 * Kept in a DLL.
69 */
70 struct DhtPutActivity *prev;
71
72 /**
73 * Handle for the DHT PUT operation.
74 */
75 struct GNUNET_DHT_PutHandle *ph;
76
77 /**
78 * When was this PUT initiated?
79 */
80 struct GNUNET_TIME_Absolute start_date;
81};
82
83
84/**
85 * Handle to the statistics service
86 */
87static struct GNUNET_STATISTICS_Handle *statistics;
88
89/**
90 * Our handle to the DHT
91 */
92static struct GNUNET_DHT_Handle *dht_handle;
93
94/**
95 * Our handle to the namestore service
96 */
97static struct GNUNET_NAMESTORE_Handle *namestore_handle;
98
99/**
100 * Handle to monitor namestore changes to instant propagation.
101 */
102static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
103
104/**
105 * Head of monitor activities; kept in a DLL.
106 */
107static struct DhtPutActivity *ma_head;
108
109/**
110 * Tail of monitor activities; kept in a DLL.
111 */
112static struct DhtPutActivity *ma_tail;
113
114/**
115 * Number of entries in the DHT queue #ma_head.
116 */
117static unsigned int ma_queue_length;
118
119/**
120 * Optimize block insertion by caching map of private keys to
121 * public keys in memory?
122 */
123static int cache_keys;
124
125
126/**
127 * Task run during shutdown.
128 *
129 * @param cls unused
130 * @param tc unused
131 */
132static void
133shutdown_task (void *cls)
134{
135 struct DhtPutActivity *ma;
136
137 (void) cls;
138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
139 "Shutting down!\n");
140 while (NULL != (ma = ma_head))
141 {
142 GNUNET_DHT_put_cancel (ma->ph);
143 ma_queue_length--;
144 GNUNET_CONTAINER_DLL_remove (ma_head,
145 ma_tail,
146 ma);
147 GNUNET_free (ma);
148 }
149 if (NULL != statistics)
150 {
151 GNUNET_STATISTICS_destroy (statistics,
152 GNUNET_NO);
153 statistics = NULL;
154 }
155 if (NULL != zmon)
156 {
157 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
158 zmon = NULL;
159 }
160 if (NULL != namestore_handle)
161 {
162 GNUNET_NAMESTORE_disconnect (namestore_handle);
163 namestore_handle = NULL;
164 }
165 if (NULL != dht_handle)
166 {
167 GNUNET_DHT_disconnect (dht_handle);
168 dht_handle = NULL;
169 }
170}
171
172
173/**
174 * Continuation called from DHT once the PUT operation triggered
175 * by a monitor is done.
176 *
177 * @param cls a `struct DhtPutActivity`
178 */
179static void
180dht_put_monitor_continuation (void *cls)
181{
182 struct DhtPutActivity *ma = cls;
183
184 GNUNET_NAMESTORE_zone_monitor_next (zmon,
185 1);
186 ma_queue_length--;
187 GNUNET_CONTAINER_DLL_remove (ma_head,
188 ma_tail,
189 ma);
190 GNUNET_free (ma);
191}
192
193
194/**
195 * Convert namestore records from the internal format to that
196 * suitable for publication (removes private records, converts
197 * to absolute expiration time).
198 *
199 * @param rd input records
200 * @param rd_count size of the @a rd and @a rd_public arrays
201 * @param rd_public where to write the converted records
202 * @return number of records written to @a rd_public
203 */
204static unsigned int
205convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
206 unsigned int rd_count,
207 struct GNUNET_GNSRECORD_Data *rd_public)
208{
209 struct GNUNET_TIME_Absolute now;
210 unsigned int rd_public_count;
211
212 rd_public_count = 0;
213 now = GNUNET_TIME_absolute_get ();
214 for (unsigned int i=0;i<rd_count;i++)
215 {
216 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
217 continue;
218 if ( (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
219 (rd[i].expiration_time < now.abs_value_us) )
220 continue; /* record already expired, skip it */
221 rd_public[rd_public_count++] = rd[i];
222 }
223 return rd_public_count;
224}
225
226
227/**
228 * Store GNS records in the DHT.
229 *
230 * @param key key of the zone
231 * @param label label to store under
232 * @param rd_public public record data
233 * @param rd_public_count number of records in @a rd_public
234 * @param ma handle for the PUT operation
235 * @return DHT PUT handle, NULL on error
236 */
237static struct GNUNET_DHT_PutHandle *
238perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
239 const char *label,
240 const struct GNUNET_GNSRECORD_Data *rd_public,
241 unsigned int rd_public_count,
242 struct DhtPutActivity *ma)
243{
244 struct GNUNET_GNSRECORD_Block *block;
245 struct GNUNET_HashCode query;
246 struct GNUNET_TIME_Absolute expire;
247 size_t block_size;
248 struct GNUNET_DHT_PutHandle *ret;
249
250 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
251 rd_public);
252 if (cache_keys)
253 block = GNUNET_GNSRECORD_block_create2 (key,
254 expire,
255 label,
256 rd_public,
257 rd_public_count);
258 else
259 block = GNUNET_GNSRECORD_block_create (key,
260 expire,
261 label,
262 rd_public,
263 rd_public_count);
264 if (NULL == block)
265 {
266 GNUNET_break (0);
267 return NULL; /* whoops */
268 }
269 block_size = ntohl (block->purpose.size)
270 + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)
271 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
272 GNUNET_GNSRECORD_query_from_private_key (key,
273 label,
274 &query);
275 GNUNET_STATISTICS_update (statistics,
276 "DHT put operations initiated",
277 1,
278 GNUNET_NO);
279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280 "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
281 rd_public_count,
282 label,
283 GNUNET_STRINGS_absolute_time_to_string (expire),
284 GNUNET_h2s (&query));
285 ret = GNUNET_DHT_put (dht_handle,
286 &query,
287 DHT_GNS_REPLICATION_LEVEL,
288 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
289 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
290 block_size,
291 block,
292 expire,
293 &dht_put_monitor_continuation,
294 ma);
295 GNUNET_free (block);
296 return ret;
297}
298
299
300/**
301 * Process a record that was stored in the namestore
302 * (invoked by the monitor).
303 *
304 * @param cls closure, NULL
305 * @param zone private key of the zone; NULL on disconnect
306 * @param label label of the records; NULL on disconnect
307 * @param rd_count number of entries in @a rd array, 0 if label was deleted
308 * @param rd array of records with data to store
309 */
310static void
311handle_monitor_event (void *cls,
312 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
313 const char *label,
314 unsigned int rd_count,
315 const struct GNUNET_GNSRECORD_Data *rd)
316{
317 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
318 unsigned int rd_public_count;
319 struct DhtPutActivity *ma;
320
321 (void) cls;
322 GNUNET_STATISTICS_update (statistics,
323 "Namestore monitor events received",
324 1,
325 GNUNET_NO);
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327 "Received %u records for label `%s' via namestore monitor\n",
328 rd_count,
329 label);
330 /* filter out records that are not public, and convert to
331 absolute expiration time. */
332 rd_public_count = convert_records_for_export (rd,
333 rd_count,
334 rd_public);
335 if (0 == rd_public_count)
336 {
337 GNUNET_NAMESTORE_zone_monitor_next (zmon,
338 1);
339 return; /* nothing to do */
340 }
341 ma = GNUNET_new (struct DhtPutActivity);
342 ma->start_date = GNUNET_TIME_absolute_get ();
343 ma->ph = perform_dht_put (zone,
344 label,
345 rd,
346 rd_count,
347 ma);
348 if (NULL == ma->ph)
349 {
350 /* PUT failed, do not remember operation */
351 GNUNET_free (ma);
352 GNUNET_NAMESTORE_zone_monitor_next (zmon,
353 1);
354 return;
355 }
356 GNUNET_CONTAINER_DLL_insert_tail (ma_head,
357 ma_tail,
358 ma);
359 ma_queue_length++;
360 if (ma_queue_length > DHT_QUEUE_LIMIT)
361 {
362 ma = ma_head;
363 GNUNET_CONTAINER_DLL_remove (ma_head,
364 ma_tail,
365 ma);
366 GNUNET_DHT_put_cancel (ma->ph);
367 ma_queue_length--;
368 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
369 "DHT PUT unconfirmed after %s, aborting PUT\n",
370 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (ma->start_date),
371 GNUNET_YES));
372 GNUNET_free (ma);
373 }
374}
375
376
377/**
378 * The zone monitor encountered an IPC error trying to to get in
379 * sync. Restart from the beginning.
380 *
381 * @param cls NULL
382 */
383static void
384handle_monitor_error (void *cls)
385{
386 (void) cls;
387 GNUNET_STATISTICS_update (statistics,
388 "Namestore monitor errors encountered",
389 1,
390 GNUNET_NO);
391}
392
393
394/**
395 * Performe zonemaster duties: watch namestore, publish records.
396 *
397 * @param cls closure
398 * @param server the initialized server
399 * @param c configuration to use
400 */
401static void
402run (void *cls,
403 const struct GNUNET_CONFIGURATION_Handle *c,
404 struct GNUNET_SERVICE_Handle *service)
405{
406 unsigned long long max_parallel_bg_queries = 128;
407
408 (void) cls;
409 (void) service;
410 namestore_handle = GNUNET_NAMESTORE_connect (c);
411 if (NULL == namestore_handle)
412 {
413 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
414 _("Failed to connect to the namestore!\n"));
415 GNUNET_SCHEDULER_shutdown ();
416 return;
417 }
418 cache_keys = GNUNET_CONFIGURATION_get_value_yesno (c,
419 "namestore",
420 "CACHE_KEYS");
421 if (GNUNET_OK ==
422 GNUNET_CONFIGURATION_get_value_number (c,
423 "zonemaster",
424 "MAX_PARALLEL_BACKGROUND_QUERIES",
425 &max_parallel_bg_queries))
426 {
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
428 "Number of allowed parallel background queries: %llu\n",
429 max_parallel_bg_queries);
430 }
431 if (0 == max_parallel_bg_queries)
432 max_parallel_bg_queries = 1;
433 dht_handle = GNUNET_DHT_connect (c,
434 (unsigned int) max_parallel_bg_queries);
435 if (NULL == dht_handle)
436 {
437 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
438 _("Could not connect to DHT!\n"));
439 GNUNET_SCHEDULER_add_now (&shutdown_task,
440 NULL);
441 return;
442 }
443
444 /* Schedule periodic put for our records. */
445 statistics = GNUNET_STATISTICS_create ("zonemaster-mon",
446 c);
447 zmon = GNUNET_NAMESTORE_zone_monitor_start (c,
448 NULL,
449 GNUNET_NO,
450 &handle_monitor_error,
451 NULL,
452 &handle_monitor_event,
453 NULL,
454 NULL /* sync_cb */,
455 NULL);
456 GNUNET_NAMESTORE_zone_monitor_next (zmon,
457 NAMESTORE_QUEUE_LIMIT - 1);
458 GNUNET_break (NULL != zmon);
459 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
460 NULL);
461}
462
463
464/**
465 * Define "main" method using service macro.
466 */
467GNUNET_SERVICE_MAIN
468("zonemaster-monitor",
469 GNUNET_SERVICE_OPTION_NONE,
470 &run,
471 NULL,
472 NULL,
473 NULL,
474 GNUNET_MQ_handler_end());
475
476
477/* end of gnunet-service-zonemaster-monitor.c */
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c
index 7129cf44f..fcc6b4226 100644
--- a/src/zonemaster/gnunet-service-zonemaster.c
+++ b/src/zonemaster/gnunet-service-zonemaster.c
@@ -1,21 +1,19 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2017 GNUnet e.V. 3 Copyright (C) 2012, 2013, 2014, 2017, 2018 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software: you can redistribute it and/or modify it
6 it under the terms of the GNU General Public License as published 6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation; either version 3, or (at your 7 by the Free Software Foundation, either version 3 of the License,
8 option) any later version. 8 or (at your option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with GNUnet; see the file COPYING. If not, write to the 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/ 17*/
20 18
21/** 19/**
@@ -29,8 +27,6 @@
29#include "gnunet_dht_service.h" 27#include "gnunet_dht_service.h"
30#include "gnunet_namestore_service.h" 28#include "gnunet_namestore_service.h"
31#include "gnunet_statistics_service.h" 29#include "gnunet_statistics_service.h"
32#include "gnunet_namestore_plugin.h"
33#include "gnunet_signatures.h"
34 30
35 31
36#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) 32#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
@@ -60,6 +56,12 @@
60#define DHT_QUEUE_LIMIT 2000 56#define DHT_QUEUE_LIMIT 2000
61 57
62/** 58/**
59 * How many events may the namestore give us before it has to wait
60 * for us to keep up?
61 */
62#define NAMESTORE_QUEUE_LIMIT 50
63
64/**
63 * The initial interval in milliseconds btween puts in 65 * The initial interval in milliseconds btween puts in
64 * a zone iteration 66 * a zone iteration
65 */ 67 */
@@ -72,23 +74,12 @@
72#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) 74#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
73 75
74/** 76/**
75 * The default put interval for the zone iteration. In case
76 * no option is found
77 */
78#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
79
80/**
81 * The factor the current zone iteration interval is divided by for each 77 * The factor the current zone iteration interval is divided by for each
82 * additional new record 78 * additional new record
83 */ 79 */
84#define LATE_ITERATION_SPEEDUP_FACTOR 2 80#define LATE_ITERATION_SPEEDUP_FACTOR 2
85 81
86/** 82/**
87 * How long until a DHT PUT attempt should time out?
88 */
89#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
90
91/**
92 * What replication level do we use for DHT PUT operations? 83 * What replication level do we use for DHT PUT operations?
93 */ 84 */
94#define DHT_GNS_REPLICATION_LEVEL 5 85#define DHT_GNS_REPLICATION_LEVEL 5
@@ -132,11 +123,6 @@ static struct GNUNET_STATISTICS_Handle *statistics;
132static struct GNUNET_DHT_Handle *dht_handle; 123static struct GNUNET_DHT_Handle *dht_handle;
133 124
134/** 125/**
135 * Active DHT put operation (or NULL)
136 */
137static struct GNUNET_DHT_PutHandle *active_put;
138
139/**
140 * Our handle to the namestore service 126 * Our handle to the namestore service
141 */ 127 */
142static struct GNUNET_NAMESTORE_Handle *namestore_handle; 128static struct GNUNET_NAMESTORE_Handle *namestore_handle;
@@ -147,21 +133,6 @@ static struct GNUNET_NAMESTORE_Handle *namestore_handle;
147static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter; 133static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
148 134
149/** 135/**
150 * Handle to monitor namestore changes to instant propagation.
151 */
152static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
153
154/**
155 * Head of monitor activities; kept in a DLL.
156 */
157static struct DhtPutActivity *ma_head;
158
159/**
160 * Tail of monitor activities; kept in a DLL.
161 */
162static struct DhtPutActivity *ma_tail;
163
164/**
165 * Head of iteration put activities; kept in a DLL. 136 * Head of iteration put activities; kept in a DLL.
166 */ 137 */
167static struct DhtPutActivity *it_head; 138static struct DhtPutActivity *it_head;
@@ -177,11 +148,6 @@ static struct DhtPutActivity *it_tail;
177static unsigned int dht_queue_length; 148static unsigned int dht_queue_length;
178 149
179/** 150/**
180 * Number of entries in the DHT queue #ma_head.
181 */
182static unsigned int ma_queue_length;
183
184/**
185 * Useful for zone update for DHT put 151 * Useful for zone update for DHT put
186 */ 152 */
187static unsigned long long num_public_records; 153static unsigned long long num_public_records;
@@ -280,17 +246,10 @@ shutdown_task (void *cls)
280 (void) cls; 246 (void) cls;
281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
282 "Shutting down!\n"); 248 "Shutting down!\n");
283 while (NULL != (ma = ma_head))
284 {
285 GNUNET_DHT_put_cancel (ma->ph);
286 GNUNET_CONTAINER_DLL_remove (ma_head,
287 ma_tail,
288 ma);
289 GNUNET_free (ma);
290 }
291 while (NULL != (ma = it_head)) 249 while (NULL != (ma = it_head))
292 { 250 {
293 GNUNET_DHT_put_cancel (ma->ph); 251 GNUNET_DHT_put_cancel (ma->ph);
252 dht_queue_length--;
294 GNUNET_CONTAINER_DLL_remove (it_head, 253 GNUNET_CONTAINER_DLL_remove (it_head,
295 it_tail, 254 it_tail,
296 ma); 255 ma);
@@ -313,21 +272,11 @@ shutdown_task (void *cls)
313 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter); 272 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
314 namestore_iter = NULL; 273 namestore_iter = NULL;
315 } 274 }
316 if (NULL != zmon)
317 {
318 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
319 zmon = NULL;
320 }
321 if (NULL != namestore_handle) 275 if (NULL != namestore_handle)
322 { 276 {
323 GNUNET_NAMESTORE_disconnect (namestore_handle); 277 GNUNET_NAMESTORE_disconnect (namestore_handle);
324 namestore_handle = NULL; 278 namestore_handle = NULL;
325 } 279 }
326 if (NULL != active_put)
327 {
328 GNUNET_DHT_put_cancel (active_put);
329 active_put = NULL;
330 }
331 if (NULL != dht_handle) 280 if (NULL != dht_handle)
332 { 281 {
333 GNUNET_DHT_disconnect (dht_handle); 282 GNUNET_DHT_disconnect (dht_handle);
@@ -364,25 +313,6 @@ publish_zone_dht_start (void *cls);
364 313
365 314
366/** 315/**
367 * Continuation called from DHT once the PUT operation triggered
368 * by a monitor is done.
369 *
370 * @param cls a `struct DhtPutActivity`
371 */
372static void
373dht_put_monitor_continuation (void *cls)
374{
375 struct DhtPutActivity *ma = cls;
376
377 ma_queue_length--;
378 GNUNET_CONTAINER_DLL_remove (ma_head,
379 ma_tail,
380 ma);
381 GNUNET_free (ma);
382}
383
384
385/**
386 * Calculate #target_iteration_velocity_per_record. 316 * Calculate #target_iteration_velocity_per_record.
387 */ 317 */
388static void 318static void
@@ -521,10 +451,6 @@ update_velocity (unsigned int cnt)
521 dht_queue_length, 451 dht_queue_length,
522 GNUNET_NO); 452 GNUNET_NO);
523 GNUNET_STATISTICS_set (statistics, 453 GNUNET_STATISTICS_set (statistics,
524 "# size of the DHT queue (mon)",
525 ma_queue_length,
526 GNUNET_NO);
527 GNUNET_STATISTICS_set (statistics,
528 "% speed increase needed for target velocity", 454 "% speed increase needed for target velocity",
529 pct, 455 pct,
530 GNUNET_NO); 456 GNUNET_NO);
@@ -558,6 +484,12 @@ check_zone_namestore_next ()
558 GNUNET_NO); 484 GNUNET_NO);
559 delay = GNUNET_TIME_relative_multiply (delay, 485 delay = GNUNET_TIME_relative_multiply (delay,
560 NS_BLOCK_SIZE); 486 NS_BLOCK_SIZE);
487 /* make sure we do not overshoot because of the #NS_BLOCK_SIZE factor */
488 delay = GNUNET_TIME_relative_min (MAXIMUM_ZONE_ITERATION_INTERVAL,
489 delay);
490 /* no delays on first iteration */
491 if (GNUNET_YES == first_zone_iteration)
492 delay = GNUNET_TIME_UNIT_ZERO;
561 GNUNET_assert (NULL == zone_publish_task); 493 GNUNET_assert (NULL == zone_publish_task);
562 zone_publish_task = GNUNET_SCHEDULER_add_delayed (delay, 494 zone_publish_task = GNUNET_SCHEDULER_add_delayed (delay,
563 &publish_zone_namestore_next, 495 &publish_zone_namestore_next,
@@ -606,24 +538,22 @@ convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
606 rd_public_count = 0; 538 rd_public_count = 0;
607 now = GNUNET_TIME_absolute_get (); 539 now = GNUNET_TIME_absolute_get ();
608 for (unsigned int i=0;i<rd_count;i++) 540 for (unsigned int i=0;i<rd_count;i++)
609 if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) 541 {
542 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
543 continue;
544 if ( (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
545 (rd[i].expiration_time < now.abs_value_us) )
546 continue; /* record already expired, skip it */
547 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
610 { 548 {
611 rd_public[rd_public_count] = rd[i]; 549 /* GNUNET_GNSRECORD_block_create will convert to absolute time;
612 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) 550 we just need to adjust our iteration frequency */
613 { 551 min_relative_record_time.rel_value_us =
614 /* GNUNET_GNSRECORD_block_create will convert to absolute time; 552 GNUNET_MIN (rd[i].expiration_time,
615 we just need to adjust our iteration frequency */ 553 min_relative_record_time.rel_value_us);
616 min_relative_record_time.rel_value_us =
617 GNUNET_MIN (rd_public[rd_public_count].expiration_time,
618 min_relative_record_time.rel_value_us);
619 }
620 else if (rd_public[rd_public_count].expiration_time < now.abs_value_us)
621 {
622 /* record already expired, skip it */
623 continue;
624 }
625 rd_public_count++;
626 } 554 }
555 rd_public[rd_public_count++] = rd[i];
556 }
627 return rd_public_count; 557 return rd_public_count;
628} 558}
629 559
@@ -635,8 +565,7 @@ convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
635 * @param label label to store under 565 * @param label label to store under
636 * @param rd_public public record data 566 * @param rd_public public record data
637 * @param rd_public_count number of records in @a rd_public 567 * @param rd_public_count number of records in @a rd_public
638 * @param cont function to call with PUT result 568 * @param ma handle for the put operation
639 * @param cont_cls closure for @a cont
640 * @return DHT PUT handle, NULL on error 569 * @return DHT PUT handle, NULL on error
641 */ 570 */
642static struct GNUNET_DHT_PutHandle * 571static struct GNUNET_DHT_PutHandle *
@@ -644,8 +573,7 @@ perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
644 const char *label, 573 const char *label,
645 const struct GNUNET_GNSRECORD_Data *rd_public, 574 const struct GNUNET_GNSRECORD_Data *rd_public,
646 unsigned int rd_public_count, 575 unsigned int rd_public_count,
647 GNUNET_SCHEDULER_TaskCallback cont, 576 struct DhtPutActivity *ma)
648 void *cont_cls)
649{ 577{
650 struct GNUNET_GNSRECORD_Block *block; 578 struct GNUNET_GNSRECORD_Block *block;
651 struct GNUNET_HashCode query; 579 struct GNUNET_HashCode query;
@@ -697,8 +625,8 @@ perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
697 block_size, 625 block_size,
698 block, 626 block,
699 expire, 627 expire,
700 cont, 628 &dht_put_continuation,
701 cont_cls); 629 ma);
702 GNUNET_free (block); 630 GNUNET_free (block);
703 return ret; 631 return ret;
704} 632}
@@ -724,11 +652,6 @@ zone_iteration_error (void *cls)
724 GNUNET_SCHEDULER_cancel (zone_publish_task); 652 GNUNET_SCHEDULER_cancel (zone_publish_task);
725 zone_publish_task = NULL; 653 zone_publish_task = NULL;
726 } 654 }
727 if (NULL != active_put)
728 {
729 GNUNET_DHT_put_cancel (active_put);
730 active_put = NULL;
731 }
732 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, 655 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
733 NULL); 656 NULL);
734} 657}
@@ -751,8 +674,7 @@ zone_iteration_finished (void *cls)
751 calculate_put_interval (); 674 calculate_put_interval ();
752 /* reset for next iteration */ 675 /* reset for next iteration */
753 min_relative_record_time 676 min_relative_record_time
754 = GNUNET_TIME_relative_multiply (GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY, 677 = GNUNET_TIME_UNIT_FOREVER_REL;
755 PUBLISH_OPS_PER_EXPIRATION);
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757 "Zone iteration finished. Adjusted zone iteration interval to %s\n", 679 "Zone iteration finished. Adjusted zone iteration interval to %s\n",
758 GNUNET_STRINGS_relative_time_to_string (target_iteration_velocity_per_record, 680 GNUNET_STRINGS_relative_time_to_string (target_iteration_velocity_per_record,
@@ -821,7 +743,6 @@ put_gns_record (void *cls,
821 label, 743 label,
822 rd_public, 744 rd_public,
823 rd_public_count, 745 rd_public_count,
824 &dht_put_continuation,
825 ma); 746 ma);
826 put_cnt++; 747 put_cnt++;
827 if (0 == put_cnt % DELTA_INTERVAL) 748 if (0 == put_cnt % DELTA_INTERVAL)
@@ -889,130 +810,6 @@ publish_zone_dht_start (void *cls)
889 810
890 811
891/** 812/**
892 * Process a record that was stored in the namestore
893 * (invoked by the monitor).
894 *
895 * @param cls closure, NULL
896 * @param zone private key of the zone; NULL on disconnect
897 * @param label label of the records; NULL on disconnect
898 * @param rd_count number of entries in @a rd array, 0 if label was deleted
899 * @param rd array of records with data to store
900 */
901static void
902handle_monitor_event (void *cls,
903 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
904 const char *label,
905 unsigned int rd_count,
906 const struct GNUNET_GNSRECORD_Data *rd)
907{
908 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
909 unsigned int rd_public_count;
910 struct DhtPutActivity *ma;
911
912 (void) cls;
913 GNUNET_STATISTICS_update (statistics,
914 "Namestore monitor events received",
915 1,
916 GNUNET_NO);
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
918 "Received %u records for label `%s' via namestore monitor\n",
919 rd_count,
920 label);
921 /* filter out records that are not public, and convert to
922 absolute expiration time. */
923 rd_public_count = convert_records_for_export (rd,
924 rd_count,
925 rd_public);
926 if (0 == rd_public_count)
927 return; /* nothing to do */
928 num_public_records++;
929 ma = GNUNET_new (struct DhtPutActivity);
930 ma->start_date = GNUNET_TIME_absolute_get ();
931 ma->ph = perform_dht_put (zone,
932 label,
933 rd,
934 rd_count,
935 &dht_put_monitor_continuation,
936 ma);
937 if (NULL == ma->ph)
938 {
939 /* PUT failed, do not remember operation */
940 GNUNET_free (ma);
941 return;
942 }
943 GNUNET_CONTAINER_DLL_insert_tail (ma_head,
944 ma_tail,
945 ma);
946 ma_queue_length++;
947 if (ma_queue_length > DHT_QUEUE_LIMIT)
948 {
949 ma = ma_head;
950 GNUNET_CONTAINER_DLL_remove (ma_head,
951 ma_tail,
952 ma);
953 GNUNET_DHT_put_cancel (ma->ph);
954 ma_queue_length--;
955 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
956 "DHT PUT unconfirmed after %s, aborting PUT\n",
957 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (ma->start_date),
958 GNUNET_YES));
959 GNUNET_free (ma);
960 }
961}
962
963
964/**
965 * The zone monitor is now in SYNC with the current state of the
966 * name store. Start to perform periodic iterations.
967 *
968 * @param cls NULL
969 */
970static void
971monitor_sync_event (void *cls)
972{
973 (void) cls;
974 if ( (NULL == zone_publish_task) &&
975 (NULL == namestore_iter) )
976 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
977 NULL);
978}
979
980
981/**
982 * The zone monitor encountered an IPC error trying to to get in
983 * sync. Restart from the beginning.
984 *
985 * @param cls NULL
986 */
987static void
988handle_monitor_error (void *cls)
989{
990 (void) cls;
991 GNUNET_STATISTICS_update (statistics,
992 "Namestore monitor errors encountered",
993 1,
994 GNUNET_NO);
995 if (NULL != zone_publish_task)
996 {
997 GNUNET_SCHEDULER_cancel (zone_publish_task);
998 zone_publish_task = NULL;
999 }
1000 if (NULL != namestore_iter)
1001 {
1002 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
1003 namestore_iter = NULL;
1004 }
1005 if (NULL != active_put)
1006 {
1007 GNUNET_DHT_put_cancel (active_put);
1008 active_put = NULL;
1009 }
1010 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
1011 NULL);
1012}
1013
1014
1015/**
1016 * Performe zonemaster duties: watch namestore, publish records. 813 * Performe zonemaster duties: watch namestore, publish records.
1017 * 814 *
1018 * @param cls closure 815 * @param cls closure
@@ -1030,8 +827,7 @@ run (void *cls,
1030 (void) service; 827 (void) service;
1031 last_put_100 = GNUNET_TIME_absolute_get (); /* first time! */ 828 last_put_100 = GNUNET_TIME_absolute_get (); /* first time! */
1032 min_relative_record_time 829 min_relative_record_time
1033 = GNUNET_TIME_relative_multiply (GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY, 830 = GNUNET_TIME_UNIT_FOREVER_REL;
1034 PUBLISH_OPS_PER_EXPIRATION);
1035 target_iteration_velocity_per_record = INITIAL_ZONE_ITERATION_INTERVAL; 831 target_iteration_velocity_per_record = INITIAL_ZONE_ITERATION_INTERVAL;
1036 namestore_handle = GNUNET_NAMESTORE_connect (c); 832 namestore_handle = GNUNET_NAMESTORE_connect (c);
1037 if (NULL == namestore_handle) 833 if (NULL == namestore_handle)
@@ -1044,7 +840,7 @@ run (void *cls,
1044 cache_keys = GNUNET_CONFIGURATION_get_value_yesno (c, 840 cache_keys = GNUNET_CONFIGURATION_get_value_yesno (c,
1045 "namestore", 841 "namestore",
1046 "CACHE_KEYS"); 842 "CACHE_KEYS");
1047 zone_publish_time_window_default = DEFAULT_ZONE_PUBLISH_TIME_WINDOW; 843 zone_publish_time_window_default = GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY;
1048 if (GNUNET_OK == 844 if (GNUNET_OK ==
1049 GNUNET_CONFIGURATION_get_value_time (c, 845 GNUNET_CONFIGURATION_get_value_time (c,
1050 "zonemaster", 846 "zonemaster",
@@ -1088,16 +884,8 @@ run (void *cls,
1088 "Target zone iteration velocity (μs)", 884 "Target zone iteration velocity (μs)",
1089 target_iteration_velocity_per_record.rel_value_us, 885 target_iteration_velocity_per_record.rel_value_us,
1090 GNUNET_NO); 886 GNUNET_NO);
1091 zmon = GNUNET_NAMESTORE_zone_monitor_start (c, 887 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
1092 NULL, 888 NULL);
1093 GNUNET_NO,
1094 &handle_monitor_error,
1095 NULL,
1096 &handle_monitor_event,
1097 NULL,
1098 &monitor_sync_event,
1099 NULL);
1100 GNUNET_break (NULL != zmon);
1101 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 889 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1102 NULL); 890 NULL);
1103} 891}
diff --git a/src/zonemaster/zonemaster.conf.in b/src/zonemaster/zonemaster.conf.in
index 871eb9c8f..58cfcb7ce 100644
--- a/src/zonemaster/zonemaster.conf.in
+++ b/src/zonemaster/zonemaster.conf.in
@@ -1,6 +1,6 @@
1[zonemaster] 1[zonemaster]
2AUTOSTART = @AUTOSTART@ 2START_ON_DEMAND = @START_ON_DEMAND@
3FORCESTART = YES 3IMMEDIATE_START = YES
4HOSTNAME = localhost 4HOSTNAME = localhost
5BINARY = gnunet-service-zonemaster 5BINARY = gnunet-service-zonemaster
6UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock 6UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock
@@ -23,3 +23,20 @@ ZONE_PUBLISH_TIME_WINDOW = 4 h
23# USE_CACHE = YES 23# USE_CACHE = YES
24 24
25# PREFIX = valgrind --leak-check=full --track-origins=yes 25# PREFIX = valgrind --leak-check=full --track-origins=yes
26
27
28
29[zonemaster-monitor]
30START_ON_DEMAND = @START_ON_DEMAND@
31IMMEDIATE_START = YES
32HOSTNAME = localhost
33BINARY = gnunet-service-zonemaster-monitor
34UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster-monitor.sock
35@JAVAPORT@PORT = 2124
36
37# Do we require users that want to access GNS to run this process
38# (usually not a good idea)
39UNIX_MATCH_UID = NO
40
41# Do we require users that want to access GNS to be in the 'gnunet' group?
42UNIX_MATCH_GID = NO