aboutsummaryrefslogtreecommitdiff
path: root/src/zonemaster
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-10-18 15:30:28 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-10-18 15:30:28 +0900
commit37f81821bc98f2342185a4bec3de044000be3596 (patch)
treeee852c2ca20d12ecf6256d1c73546030800de858 /src/zonemaster
parent42f3c98219a9878c7493945bb33d89b326ff14a5 (diff)
downloadgnunet-37f81821bc98f2342185a4bec3de044000be3596.tar.gz
gnunet-37f81821bc98f2342185a4bec3de044000be3596.zip
ZONEMASTER: Merge monitor into zonemaster process
Diffstat (limited to 'src/zonemaster')
-rw-r--r--src/zonemaster/Makefile.am16
-rw-r--r--src/zonemaster/gnunet-service-zonemaster-monitor.c612
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c283
-rw-r--r--src/zonemaster/zonemaster.conf.in18
4 files changed, 277 insertions, 652 deletions
diff --git a/src/zonemaster/Makefile.am b/src/zonemaster/Makefile.am
index 90b70f58a..ef82fc19b 100644
--- a/src/zonemaster/Makefile.am
+++ b/src/zonemaster/Makefile.am
@@ -16,8 +16,7 @@ if USE_COVERAGE
16endif 16endif
17 17
18libexec_PROGRAMS = \ 18libexec_PROGRAMS = \
19 gnunet-service-zonemaster \ 19 gnunet-service-zonemaster
20 gnunet-service-zonemaster-monitor
21 20
22gnunet_service_zonemaster_SOURCES = \ 21gnunet_service_zonemaster_SOURCES = \
23 gnunet-service-zonemaster.c 22 gnunet-service-zonemaster.c
@@ -30,16 +29,3 @@ gnunet_service_zonemaster_LDADD = \
30 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 29 $(top_builddir)/src/namestore/libgnunetnamestore.la \
31 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 30 $(top_builddir)/src/namecache/libgnunetnamecache.la \
32 $(GN_LIBINTL) 31 $(GN_LIBINTL)
33
34
35gnunet_service_zonemaster_monitor_SOURCES = \
36 gnunet-service-zonemaster-monitor.c
37gnunet_service_zonemaster_monitor_LDADD = \
38 $(top_builddir)/src/dht/libgnunetdht.la \
39 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
40 $(top_builddir)/src/identity/libgnunetidentity.la \
41 $(top_builddir)/src/statistics/libgnunetstatistics.la \
42 $(top_builddir)/src/util/libgnunetutil.la \
43 $(top_builddir)/src/namestore/libgnunetnamestore.la \
44 $(top_builddir)/src/namecache/libgnunetnamecache.la \
45 $(GN_LIBINTL)
diff --git a/src/zonemaster/gnunet-service-zonemaster-monitor.c b/src/zonemaster/gnunet-service-zonemaster-monitor.c
deleted file mode 100644
index fae97cb96..000000000
--- a/src/zonemaster/gnunet-service-zonemaster-monitor.c
+++ /dev/null
@@ -1,612 +0,0 @@
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file zonemaster/gnunet-service-zonemaster-monitor.c
23 * @brief monitor namestore changes and publish them immediately to GNUnet name system
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_dht_service.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_namecache_service.h"
31#include "gnunet_statistics_service.h"
32
33#define LOG_STRERROR_FILE(kind, syscall, \
34 filename) GNUNET_log_from_strerror_file (kind, "util", \
35 syscall, \
36 filename)
37
38
39/**
40 * How often should we (re)publish each record before
41 * it expires?
42 */
43#define PUBLISH_OPS_PER_EXPIRATION 4
44
45/**
46 * How many pending DHT operations do we allow at most?
47 */
48#define DHT_QUEUE_LIMIT 2000
49
50/**
51 * How many events may the namestore give us before it has to wait
52 * for us to keep up?
53 */
54#define NAMESTORE_QUEUE_LIMIT 5
55
56/**
57 * What replication level do we use for DHT PUT operations?
58 */
59#define DHT_GNS_REPLICATION_LEVEL 5
60
61/**
62 * Handle for DHT PUT activity triggered from the namestore monitor.
63 */
64struct DhtPutActivity
65{
66 /**
67 * Kept in a DLL.
68 */
69 struct DhtPutActivity *next;
70
71 /**
72 * Kept in a DLL.
73 */
74 struct DhtPutActivity *prev;
75
76 /**
77 * Handle for the DHT PUT operation.
78 */
79 struct GNUNET_DHT_PutHandle *ph;
80
81 /**
82 * When was this PUT initiated?
83 */
84 struct GNUNET_TIME_Absolute start_date;
85};
86
87/**
88 * Pending operation on the namecache.
89 */
90struct CacheOperation
91{
92 /**
93 * Kept in a DLL.
94 */
95 struct CacheOperation *prev;
96
97 /**
98 * Kept in a DLL.
99 */
100 struct CacheOperation *next;
101
102 /**
103 * Handle to namecache queue.
104 */
105 struct GNUNET_NAMECACHE_QueueEntry *qe;
106
107};
108
109
110/**
111 * Handle to the statistics service
112 */
113static struct GNUNET_STATISTICS_Handle *statistics;
114
115/**
116 * Our handle to the DHT
117 */
118static struct GNUNET_DHT_Handle *dht_handle;
119
120/**
121 * Our handle to the namestore service
122 */
123static struct GNUNET_NAMESTORE_Handle *namestore_handle;
124
125/**
126 * Handle to monitor namestore changes to instant propagation.
127 */
128static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
129
130/**
131 * Head of monitor activities; kept in a DLL.
132 */
133static struct DhtPutActivity *ma_head;
134
135/**
136 * Tail of monitor activities; kept in a DLL.
137 */
138static struct DhtPutActivity *ma_tail;
139
140/**
141 * Our handle to the namecache service
142 */
143static struct GNUNET_NAMECACHE_Handle *namecache;
144
145/**
146 * Use the namecache? Doing so creates additional cryptographic
147 * operations whenever we touch a record.
148 */
149static int disable_namecache;
150
151
152/**
153 * Number of entries in the DHT queue #ma_head.
154 */
155static unsigned int ma_queue_length;
156
157/**
158 * Optimize block insertion by caching map of private keys to
159 * public keys in memory?
160 */
161static int cache_keys;
162
163/**
164 * Head of cop DLL.
165 */
166static struct CacheOperation *cop_head;
167
168/**
169 * Tail of cop DLL.
170 */
171static struct CacheOperation *cop_tail;
172
173
174/**
175 * Task run during shutdown.
176 *
177 * @param cls unused
178 * @param tc unused
179 */
180static void
181shutdown_task (void *cls)
182{
183 struct DhtPutActivity *ma;
184 struct CacheOperation *cop;
185
186
187 (void) cls;
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Shutting down!\n");
190 while (NULL != (cop = cop_head))
191 {
192 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
193 "Aborting incomplete namecache operation\n");
194 GNUNET_NAMECACHE_cancel (cop->qe);
195 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
196 GNUNET_free (cop);
197 }
198 while (NULL != (ma = ma_head))
199 {
200 GNUNET_DHT_put_cancel (ma->ph);
201 ma_queue_length--;
202 GNUNET_CONTAINER_DLL_remove (ma_head,
203 ma_tail,
204 ma);
205 GNUNET_free (ma);
206 }
207 if (NULL != statistics)
208 {
209 GNUNET_STATISTICS_destroy (statistics,
210 GNUNET_NO);
211 statistics = NULL;
212 }
213 if (NULL != zmon)
214 {
215 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
216 zmon = NULL;
217 }
218 if (NULL != namestore_handle)
219 {
220 GNUNET_NAMESTORE_disconnect (namestore_handle);
221 namestore_handle = NULL;
222 }
223 if (NULL != namecache)
224 {
225 GNUNET_NAMECACHE_disconnect (namecache);
226 namecache = NULL;
227 }
228 if (NULL != dht_handle)
229 {
230 GNUNET_DHT_disconnect (dht_handle);
231 dht_handle = NULL;
232 }
233}
234
235/**
236 * Cache operation complete, clean up.
237 *
238 * @param cls the `struct CacheOperation`
239 * @param success success
240 * @param emsg error messages
241 */
242static void
243finish_cache_operation (void *cls, int32_t success, const char *emsg)
244{
245 struct CacheOperation *cop = cls;
246
247 if (NULL != emsg)
248 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
249 _ ("Failed to replicate block in namecache: %s\n"),
250 emsg);
251 else
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
253 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
254 GNUNET_free (cop);
255}
256
257
258/**
259 * Refresh the (encrypted) block in the namecache.
260 *
261 * @param zone_key private key of the zone
262 * @param name label for the records
263 * @param rd_count number of records
264 * @param rd records stored under the given @a name
265 */
266static void
267refresh_block (const struct GNUNET_GNSRECORD_Block *block)
268{
269 struct CacheOperation *cop;
270
271 if (GNUNET_YES == disable_namecache)
272 {
273 GNUNET_STATISTICS_update (statistics,
274 "Namecache updates skipped (NC disabled)",
275 1,
276 GNUNET_NO);
277 return;
278 }
279 GNUNET_assert (NULL != block);
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching block in namecache\n");
281 GNUNET_STATISTICS_update (statistics,
282 "Namecache updates pushed",
283 1,
284 GNUNET_NO);
285 cop = GNUNET_new (struct CacheOperation);
286 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
287 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
288 block,
289 &finish_cache_operation,
290 cop);
291}
292
293
294
295/**
296 * Continuation called from DHT once the PUT operation triggered
297 * by a monitor is done.
298 *
299 * @param cls a `struct DhtPutActivity`
300 */
301static void
302dht_put_monitor_continuation (void *cls)
303{
304 struct DhtPutActivity *ma = cls;
305
306 GNUNET_NAMESTORE_zone_monitor_next (zmon,
307 1);
308 ma_queue_length--;
309 GNUNET_CONTAINER_DLL_remove (ma_head,
310 ma_tail,
311 ma);
312 GNUNET_free (ma);
313}
314
315
316/**
317 * Store GNS records in the DHT.
318 *
319 * @param key key of the zone
320 * @param label label to store under
321 * @param rd_public public record data
322 * @param rd_public_count number of records in @a rd_public
323 * @param ma handle for the PUT operation
324 * @return DHT PUT handle, NULL on error
325 */
326static struct GNUNET_DHT_PutHandle *
327perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
328 const char *label,
329 const struct GNUNET_GNSRECORD_Data *rd,
330 unsigned int rd_count,
331 struct GNUNET_TIME_Absolute expire,
332 struct DhtPutActivity *ma)
333{
334 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
335 struct GNUNET_GNSRECORD_Block *block;
336 struct GNUNET_GNSRECORD_Block *block_priv;
337 struct GNUNET_HashCode query;
338 struct GNUNET_TIME_Absolute expire_priv;
339 size_t block_size;
340 unsigned int rd_public_count = 0;
341 struct GNUNET_DHT_PutHandle *ret;
342 char *emsg;
343
344 if (GNUNET_OK !=
345 GNUNET_GNSRECORD_normalize_record_set (label,
346 rd,
347 rd_count,
348 rd_public,
349 &rd_public_count,
350 &expire_priv,
351 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE,
352 &emsg))
353 {
354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
355 "%s\n", emsg);
356 GNUNET_free (emsg);
357 }
358
359 if (cache_keys)
360 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
361 expire,
362 label,
363 rd_public,
364 rd_public_count,
365 &block));
366 else
367 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
368 expire,
369 label,
370 rd_public,
371 rd_public_count,
372 &block));
373 if (NULL == block)
374 {
375 GNUNET_break (0);
376 return NULL; /* whoops */
377 }
378 if (rd_count != rd_public_count)
379 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
380 expire_priv,
381 label,
382 rd,
383 rd_count,
384 &block_priv));
385 else
386 block_priv = block;
387 block_size = GNUNET_GNSRECORD_block_get_size (block);
388 GNUNET_GNSRECORD_query_from_private_key (key,
389 label,
390 &query);
391 GNUNET_STATISTICS_update (statistics,
392 "DHT put operations initiated",
393 1,
394 GNUNET_NO);
395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
396 "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
397 rd_public_count,
398 label,
399 GNUNET_STRINGS_absolute_time_to_string (expire),
400 GNUNET_h2s (&query));
401 ret = GNUNET_DHT_put (dht_handle,
402 &query,
403 DHT_GNS_REPLICATION_LEVEL,
404 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
405 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
406 block_size,
407 block,
408 expire,
409 &dht_put_monitor_continuation,
410 ma);
411 refresh_block (block_priv);
412 if (block != block_priv)
413 GNUNET_free (block_priv);
414 GNUNET_free (block);
415 return ret;
416}
417
418/**
419 * Process a record that was stored in the namestore
420 * (invoked by the monitor).
421 *
422 * @param cls closure, NULL
423 * @param zone private key of the zone; NULL on disconnect
424 * @param label label of the records; NULL on disconnect
425 * @param rd_count number of entries in @a rd array, 0 if label was deleted
426 * @param rd array of records with data to store
427 * @param expire expiration of this record set
428 */
429static void
430handle_monitor_event (void *cls,
431 const struct GNUNET_IDENTITY_PrivateKey *zone,
432 const char *label,
433 unsigned int rd_count,
434 const struct GNUNET_GNSRECORD_Data *rd,
435 struct GNUNET_TIME_Absolute expire)
436{
437 struct DhtPutActivity *ma;
438
439 (void) cls;
440 GNUNET_STATISTICS_update (statistics,
441 "Namestore monitor events received",
442 1,
443 GNUNET_NO);
444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
445 "Received %u records for label `%s' via namestore monitor\n",
446 rd_count,
447 label);
448 if (0 == rd_count)
449 {
450 GNUNET_NAMESTORE_zone_monitor_next (zmon,
451 1);
452 return; /* nothing to do */
453 }
454 ma = GNUNET_new (struct DhtPutActivity);
455 ma->start_date = GNUNET_TIME_absolute_get ();
456 ma->ph = perform_dht_put (zone,
457 label,
458 rd,
459 rd_count,
460 expire,
461 ma);
462 if (NULL == ma->ph)
463 {
464 /* PUT failed, do not remember operation */
465 GNUNET_free (ma);
466 GNUNET_NAMESTORE_zone_monitor_next (zmon,
467 1);
468 return;
469 }
470 GNUNET_CONTAINER_DLL_insert_tail (ma_head,
471 ma_tail,
472 ma);
473 ma_queue_length++;
474 if (ma_queue_length > DHT_QUEUE_LIMIT)
475 {
476 ma = ma_head;
477 GNUNET_CONTAINER_DLL_remove (ma_head,
478 ma_tail,
479 ma);
480 GNUNET_DHT_put_cancel (ma->ph);
481 ma_queue_length--;
482 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
483 "DHT PUT unconfirmed after %s, aborting PUT\n",
484 GNUNET_STRINGS_relative_time_to_string (
485 GNUNET_TIME_absolute_get_duration (ma->start_date),
486 GNUNET_YES));
487 GNUNET_free (ma);
488 }
489}
490
491
492/**
493 * The zone monitor encountered an IPC error trying to to get in
494 * sync. Restart from the beginning.
495 *
496 * @param cls NULL
497 */
498static void
499handle_monitor_error (void *cls)
500{
501 (void) cls;
502 GNUNET_STATISTICS_update (statistics,
503 "Namestore monitor errors encountered",
504 1,
505 GNUNET_NO);
506}
507
508
509/**
510 * Perform zonemaster duties: watch namestore, publish records.
511 *
512 * @param cls closure
513 * @param server the initialized server
514 * @param c configuration to use
515 */
516static void
517run (void *cls,
518 const struct GNUNET_CONFIGURATION_Handle *c,
519 struct GNUNET_SERVICE_Handle *service)
520{
521 unsigned long long max_parallel_bg_queries = 128;
522
523 (void) cls;
524 (void) service;
525 namestore_handle = GNUNET_NAMESTORE_connect (c);
526 if (NULL == namestore_handle)
527 {
528 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
529 _ ("Failed to connect to the namestore!\n"));
530 GNUNET_SCHEDULER_shutdown ();
531 return;
532 }
533 disable_namecache = GNUNET_CONFIGURATION_get_value_yesno (c,
534 "namecache",
535 "DISABLE");
536 if (GNUNET_NO == disable_namecache)
537 {
538 namecache = GNUNET_NAMECACHE_connect (c);
539 if (NULL == namecache)
540 {
541 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
542 _ ("Failed to connect to the namecache!\n"));
543 GNUNET_SCHEDULER_shutdown ();
544 return;
545 }
546 }
547 else
548 {
549 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
550 _ ("Namecache is disabled!\n"));
551 }
552 cache_keys = GNUNET_CONFIGURATION_get_value_yesno (c,
553 "namestore",
554 "CACHE_KEYS");
555 if (GNUNET_OK ==
556 GNUNET_CONFIGURATION_get_value_number (c,
557 "zonemaster",
558 "MAX_PARALLEL_BACKGROUND_QUERIES",
559 &max_parallel_bg_queries))
560 {
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
562 "Number of allowed parallel background queries: %llu\n",
563 max_parallel_bg_queries);
564 }
565 if (0 == max_parallel_bg_queries)
566 max_parallel_bg_queries = 1;
567 dht_handle = GNUNET_DHT_connect (c,
568 (unsigned int) max_parallel_bg_queries);
569 if (NULL == dht_handle)
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 _ ("Could not connect to DHT!\n"));
573 GNUNET_SCHEDULER_add_now (&shutdown_task,
574 NULL);
575 return;
576 }
577
578 /* Schedule periodic put for our records. */
579 statistics = GNUNET_STATISTICS_create ("zonemaster-mon",
580 c);
581 zmon = GNUNET_NAMESTORE_zone_monitor_start2 (c,
582 NULL,
583 GNUNET_NO,
584 &handle_monitor_error,
585 NULL,
586 &handle_monitor_event,
587 NULL,
588 NULL /* sync_cb */,
589 NULL,
590 GNUNET_GNSRECORD_FILTER_NONE);
591 GNUNET_NAMESTORE_zone_monitor_next (zmon,
592 NAMESTORE_QUEUE_LIMIT - 1);
593 GNUNET_break (NULL != zmon);
594 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
595 NULL);
596}
597
598
599/**
600 * Define "main" method using service macro.
601 */
602GNUNET_SERVICE_MAIN
603 ("zonemaster-monitor",
604 GNUNET_SERVICE_OPTION_NONE,
605 &run,
606 NULL,
607 NULL,
608 NULL,
609 GNUNET_MQ_handler_end ());
610
611
612/* end of gnunet-service-zonemaster-monitor.c */
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c
index 9f5d9b47a..f5c1d781b 100644
--- a/src/zonemaster/gnunet-service-zonemaster.c
+++ b/src/zonemaster/gnunet-service-zonemaster.c
@@ -67,6 +67,12 @@
67#define NAMESTORE_QUEUE_LIMIT 50 67#define NAMESTORE_QUEUE_LIMIT 50
68 68
69/** 69/**
70 * How many events may the namestore give us before it has to wait
71 * for us to keep up?
72 */
73#define NAMESTORE_MONITOR_QUEUE_LIMIT 5
74
75/**
70 * The initial interval in milliseconds btween puts in 76 * The initial interval in milliseconds btween puts in
71 * a zone iteration 77 * a zone iteration
72 */ 78 */
@@ -155,6 +161,21 @@ static struct GNUNET_DHT_Handle *dht_handle;
155static struct GNUNET_NAMESTORE_Handle *namestore_handle; 161static struct GNUNET_NAMESTORE_Handle *namestore_handle;
156 162
157/** 163/**
164 * Handle to monitor namestore changes to instant propagation.
165 */
166static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
167
168/**
169 * Head of monitor activities; kept in a DLL.
170 */
171static struct DhtPutActivity *ma_head;
172
173/**
174 * Tail of monitor activities; kept in a DLL.
175 */
176static struct DhtPutActivity *ma_tail;
177
178/**
158 * Our handle to the namecache service 179 * Our handle to the namecache service
159 */ 180 */
160static struct GNUNET_NAMECACHE_Handle *namecache; 181static struct GNUNET_NAMECACHE_Handle *namecache;
@@ -166,6 +187,11 @@ static struct GNUNET_NAMECACHE_Handle *namecache;
166static int disable_namecache; 187static int disable_namecache;
167 188
168/** 189/**
190 * Number of entries in the DHT queue #ma_head.
191 */
192static unsigned int ma_queue_length;
193
194/**
169 * Handle to iterate over our authoritative zone in namestore 195 * Handle to iterate over our authoritative zone in namestore
170 */ 196 */
171static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter; 197static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
@@ -314,6 +340,15 @@ shutdown_task (void *cls)
314 dht_queue_length--; 340 dht_queue_length--;
315 GNUNET_free (ma); 341 GNUNET_free (ma);
316 } 342 }
343 while (NULL != (ma = ma_head))
344 {
345 GNUNET_DHT_put_cancel (ma->ph);
346 ma_queue_length--;
347 GNUNET_CONTAINER_DLL_remove (ma_head,
348 ma_tail,
349 ma);
350 GNUNET_free (ma);
351 }
317 if (NULL != statistics) 352 if (NULL != statistics)
318 { 353 {
319 GNUNET_STATISTICS_destroy (statistics, 354 GNUNET_STATISTICS_destroy (statistics,
@@ -330,6 +365,11 @@ shutdown_task (void *cls)
330 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter); 365 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
331 namestore_iter = NULL; 366 namestore_iter = NULL;
332 } 367 }
368 if (NULL != zmon)
369 {
370 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
371 zmon = NULL;
372 }
333 if (NULL != namestore_handle) 373 if (NULL != namestore_handle)
334 { 374 {
335 GNUNET_NAMESTORE_disconnect (namestore_handle); 375 GNUNET_NAMESTORE_disconnect (namestore_handle);
@@ -340,7 +380,7 @@ shutdown_task (void *cls)
340 GNUNET_NAMECACHE_disconnect (namecache); 380 GNUNET_NAMECACHE_disconnect (namecache);
341 namecache = NULL; 381 namecache = NULL;
342 } 382 }
343if (NULL != dht_handle) 383 if (NULL != dht_handle)
344 { 384 {
345 GNUNET_DHT_disconnect (dht_handle); 385 GNUNET_DHT_disconnect (dht_handle);
346 dht_handle = NULL; 386 dht_handle = NULL;
@@ -666,7 +706,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
666 struct GNUNET_GNSRECORD_Block *block; 706 struct GNUNET_GNSRECORD_Block *block;
667 struct GNUNET_GNSRECORD_Block *block_priv; 707 struct GNUNET_GNSRECORD_Block *block_priv;
668 struct GNUNET_HashCode query; 708 struct GNUNET_HashCode query;
669 struct GNUNET_TIME_Absolute expire_priv; 709 struct GNUNET_TIME_Absolute expire_pub;
670 size_t block_size; 710 size_t block_size;
671 unsigned int rd_public_count = 0; 711 unsigned int rd_public_count = 0;
672 struct GNUNET_DHT_PutHandle *ret; 712 struct GNUNET_DHT_PutHandle *ret;
@@ -678,7 +718,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
678 rd_count, 718 rd_count,
679 rd_public, 719 rd_public,
680 &rd_public_count, 720 &rd_public_count,
681 &expire_priv, 721 &expire_pub,
682 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE, 722 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE,
683 &emsg)) 723 &emsg))
684 { 724 {
@@ -690,7 +730,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
690 if (cache_keys) 730 if (cache_keys)
691 { 731 {
692 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key, 732 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
693 expire, 733 expire_pub,
694 label, 734 label,
695 rd_public, 735 rd_public,
696 rd_public_count, 736 rd_public_count,
@@ -699,7 +739,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
699 else 739 else
700 { 740 {
701 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key, 741 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
702 expire, 742 expire_pub,
703 label, 743 label,
704 rd_public, 744 rd_public,
705 rd_public_count, 745 rd_public_count,
@@ -712,7 +752,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
712 } 752 }
713 if (rd_count != rd_public_count) 753 if (rd_count != rd_public_count)
714 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key, 754 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
715 expire_priv, 755 expire,
716 label, 756 label,
717 rd, 757 rd,
718 rd_count, 758 rd_count,
@@ -741,7 +781,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
741 GNUNET_BLOCK_TYPE_GNS_NAMERECORD, 781 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
742 block_size, 782 block_size,
743 block, 783 block,
744 expire, 784 expire_pub,
745 &dht_put_continuation, 785 &dht_put_continuation,
746 ma); 786 ma);
747 refresh_block (block_priv); 787 refresh_block (block_priv);
@@ -943,6 +983,221 @@ publish_zone_dht_start (void *cls)
943 983
944 984
945/** 985/**
986 * Continuation called from DHT once the PUT operation triggered
987 * by a monitor is done.
988 *
989 * @param cls a `struct DhtPutActivity`
990 */
991static void
992dht_put_monitor_continuation (void *cls)
993{
994 struct DhtPutActivity *ma = cls;
995
996 GNUNET_NAMESTORE_zone_monitor_next (zmon,
997 1);
998 ma_queue_length--;
999 GNUNET_CONTAINER_DLL_remove (ma_head,
1000 ma_tail,
1001 ma);
1002 GNUNET_free (ma);
1003}
1004
1005
1006/**
1007 * Store GNS records in the DHT.
1008 *
1009 * @param key key of the zone
1010 * @param label label to store under
1011 * @param rd_public public record data
1012 * @param rd_public_count number of records in @a rd_public
1013 * @param ma handle for the PUT operation
1014 * @return DHT PUT handle, NULL on error
1015 */
1016static struct GNUNET_DHT_PutHandle *
1017perform_dht_put_monitor (const struct GNUNET_IDENTITY_PrivateKey *key,
1018 const char *label,
1019 const struct GNUNET_GNSRECORD_Data *rd,
1020 unsigned int rd_count,
1021 struct GNUNET_TIME_Absolute expire,
1022 struct DhtPutActivity *ma)
1023{
1024 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
1025 struct GNUNET_GNSRECORD_Block *block;
1026 struct GNUNET_GNSRECORD_Block *block_priv;
1027 struct GNUNET_HashCode query;
1028 struct GNUNET_TIME_Absolute expire_pub;
1029 size_t block_size;
1030 unsigned int rd_public_count = 0;
1031 struct GNUNET_DHT_PutHandle *ret;
1032 char *emsg;
1033
1034 if (GNUNET_OK !=
1035 GNUNET_GNSRECORD_normalize_record_set (label,
1036 rd,
1037 rd_count,
1038 rd_public,
1039 &rd_public_count,
1040 &expire_pub,
1041 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE,
1042 &emsg))
1043 {
1044 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1045 "%s\n", emsg);
1046 GNUNET_free (emsg);
1047 }
1048
1049 if (cache_keys)
1050 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
1051 expire_pub,
1052 label,
1053 rd_public,
1054 rd_public_count,
1055 &block));
1056 else
1057 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
1058 expire_pub,
1059 label,
1060 rd_public,
1061 rd_public_count,
1062 &block));
1063 if (NULL == block)
1064 {
1065 GNUNET_break (0);
1066 return NULL; /* whoops */
1067 }
1068 if (rd_count != rd_public_count)
1069 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
1070 expire,
1071 label,
1072 rd,
1073 rd_count,
1074 &block_priv));
1075 else
1076 block_priv = block;
1077 block_size = GNUNET_GNSRECORD_block_get_size (block);
1078 GNUNET_GNSRECORD_query_from_private_key (key,
1079 label,
1080 &query);
1081 GNUNET_STATISTICS_update (statistics,
1082 "DHT put operations initiated",
1083 1,
1084 GNUNET_NO);
1085 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1086 "Storing %u public of %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
1087 rd_public_count,
1088 rd_count,
1089 label,
1090 GNUNET_STRINGS_absolute_time_to_string (expire),
1091 GNUNET_h2s (&query));
1092 ret = GNUNET_DHT_put (dht_handle,
1093 &query,
1094 DHT_GNS_REPLICATION_LEVEL,
1095 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
1096 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1097 block_size,
1098 block,
1099 expire_pub,
1100 &dht_put_monitor_continuation,
1101 ma);
1102 refresh_block (block_priv);
1103 if (block != block_priv)
1104 GNUNET_free (block_priv);
1105 GNUNET_free (block);
1106 return ret;
1107}
1108
1109/**
1110 * Process a record that was stored in the namestore
1111 * (invoked by the monitor).
1112 *
1113 * @param cls closure, NULL
1114 * @param zone private key of the zone; NULL on disconnect
1115 * @param label label of the records; NULL on disconnect
1116 * @param rd_count number of entries in @a rd array, 0 if label was deleted
1117 * @param rd array of records with data to store
1118 * @param expire expiration of this record set
1119 */
1120static void
1121handle_monitor_event (void *cls,
1122 const struct GNUNET_IDENTITY_PrivateKey *zone,
1123 const char *label,
1124 unsigned int rd_count,
1125 const struct GNUNET_GNSRECORD_Data *rd,
1126 struct GNUNET_TIME_Absolute expire)
1127{
1128 struct DhtPutActivity *ma;
1129
1130 (void) cls;
1131 GNUNET_STATISTICS_update (statistics,
1132 "Namestore monitor events received",
1133 1,
1134 GNUNET_NO);
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1136 "Received %u records for label `%s' via namestore monitor\n",
1137 rd_count,
1138 label);
1139 if (0 == rd_count)
1140 {
1141 GNUNET_NAMESTORE_zone_monitor_next (zmon,
1142 1);
1143 return; /* nothing to do */
1144 }
1145 ma = GNUNET_new (struct DhtPutActivity);
1146 ma->start_date = GNUNET_TIME_absolute_get ();
1147 ma->ph = perform_dht_put_monitor (zone,
1148 label,
1149 rd,
1150 rd_count,
1151 expire,
1152 ma);
1153 if (NULL == ma->ph)
1154 {
1155 /* PUT failed, do not remember operation */
1156 GNUNET_free (ma);
1157 GNUNET_NAMESTORE_zone_monitor_next (zmon,
1158 1);
1159 return;
1160 }
1161 GNUNET_CONTAINER_DLL_insert_tail (ma_head,
1162 ma_tail,
1163 ma);
1164 ma_queue_length++;
1165 if (ma_queue_length > DHT_QUEUE_LIMIT)
1166 {
1167 ma = ma_head;
1168 GNUNET_CONTAINER_DLL_remove (ma_head,
1169 ma_tail,
1170 ma);
1171 GNUNET_DHT_put_cancel (ma->ph);
1172 ma_queue_length--;
1173 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1174 "DHT PUT unconfirmed after %s, aborting PUT\n",
1175 GNUNET_STRINGS_relative_time_to_string (
1176 GNUNET_TIME_absolute_get_duration (ma->start_date),
1177 GNUNET_YES));
1178 GNUNET_free (ma);
1179 }
1180}
1181
1182
1183/**
1184 * The zone monitor encountered an IPC error trying to to get in
1185 * sync. Restart from the beginning.
1186 *
1187 * @param cls NULL
1188 */
1189static void
1190handle_monitor_error (void *cls)
1191{
1192 (void) cls;
1193 GNUNET_STATISTICS_update (statistics,
1194 "Namestore monitor errors encountered",
1195 1,
1196 GNUNET_NO);
1197}
1198
1199
1200/**
946 * Perform zonemaster duties: watch namestore, publish records. 1201 * Perform zonemaster duties: watch namestore, publish records.
947 * 1202 *
948 * @param cls closure 1203 * @param cls closure
@@ -1034,6 +1289,20 @@ run (void *cls,
1034 GNUNET_NO); 1289 GNUNET_NO);
1035 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, 1290 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
1036 NULL); 1291 NULL);
1292 zmon = GNUNET_NAMESTORE_zone_monitor_start2 (c,
1293 NULL,
1294 GNUNET_NO,
1295 &handle_monitor_error,
1296 NULL,
1297 &handle_monitor_event,
1298 NULL,
1299 NULL /* sync_cb */,
1300 NULL,
1301 GNUNET_GNSRECORD_FILTER_NONE);
1302 GNUNET_NAMESTORE_zone_monitor_next (zmon,
1303 NAMESTORE_MONITOR_QUEUE_LIMIT - 1);
1304 GNUNET_break (NULL != zmon);
1305
1037 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1306 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1038 NULL); 1307 NULL);
1039} 1308}
diff --git a/src/zonemaster/zonemaster.conf.in b/src/zonemaster/zonemaster.conf.in
index 315388417..560239944 100644
--- a/src/zonemaster/zonemaster.conf.in
+++ b/src/zonemaster/zonemaster.conf.in
@@ -24,21 +24,3 @@ ZONE_PUBLISH_TIME_WINDOW = 4 h
24# USE_CACHE = YES 24# USE_CACHE = YES
25 25
26# PREFIX = valgrind --leak-check=full --track-origins=yes 26# PREFIX = valgrind --leak-check=full --track-origins=yes
27
28
29
30[zonemaster-monitor]
31START_ON_DEMAND = @START_ON_DEMAND@
32RUN_PER_USER = YES
33IMMEDIATE_START = YES
34HOSTNAME = localhost
35BINARY = gnunet-service-zonemaster-monitor
36UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster-monitor.sock
37@JAVAPORT@PORT = 2124
38
39# Do we require users that want to access GNS to run this process
40# (usually not a good idea)
41UNIX_MATCH_UID = NO
42
43# Do we require users that want to access GNS to be in the 'gnunet' group?
44UNIX_MATCH_GID = NO