aboutsummaryrefslogtreecommitdiff
path: root/src/zonemaster
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2022-10-25 09:59:23 +0200
committert3sserakt <t3ss@posteo.de>2022-10-25 10:02:01 +0200
commitb3a76100568e15660211945d931173f858156169 (patch)
tree54d89d7a0b743df81b5df095f60c3f13c016c69d /src/zonemaster
parentc5f3eb40c97b2bcad7537607ca870a925aa9bed8 (diff)
parentfa48dbb242415a8dc06465863054b8d61c0e26bb (diff)
downloadgnunet-b3a76100568e15660211945d931173f858156169.tar.gz
gnunet-b3a76100568e15660211945d931173f858156169.zip
Merge branch 'master' of ssh://git.gnunet.org/gnunet
Diffstat (limited to 'src/zonemaster')
-rw-r--r--src/zonemaster/Makefile.am19
-rw-r--r--src/zonemaster/gnunet-service-zonemaster-monitor.c612
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c589
-rw-r--r--src/zonemaster/zonemaster.conf.in19
4 files changed, 506 insertions, 733 deletions
diff --git a/src/zonemaster/Makefile.am b/src/zonemaster/Makefile.am
index 90b70f58a..635c195ed 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
@@ -29,17 +28,5 @@ gnunet_service_zonemaster_LDADD = \
29 $(top_builddir)/src/util/libgnunetutil.la \ 28 $(top_builddir)/src/util/libgnunetutil.la \
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 32 -lpthread
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..3d87e232b 100644
--- a/src/zonemaster/gnunet-service-zonemaster.c
+++ b/src/zonemaster/gnunet-service-zonemaster.c
@@ -24,6 +24,7 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include <pthread.h>
27#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
28#include "gnunet_dnsparser_lib.h" 29#include "gnunet_dnsparser_lib.h"
29#include "gnunet_dht_service.h" 30#include "gnunet_dht_service.h"
@@ -67,6 +68,12 @@
67#define NAMESTORE_QUEUE_LIMIT 50 68#define NAMESTORE_QUEUE_LIMIT 50
68 69
69/** 70/**
71 * How many events may the namestore give us before it has to wait
72 * for us to keep up?
73 */
74#define NAMESTORE_MONITOR_QUEUE_LIMIT 5
75
76/**
70 * The initial interval in milliseconds btween puts in 77 * The initial interval in milliseconds btween puts in
71 * a zone iteration 78 * a zone iteration
72 */ 79 */
@@ -91,6 +98,86 @@
91#define DHT_GNS_REPLICATION_LEVEL 5 98#define DHT_GNS_REPLICATION_LEVEL 5
92 99
93/** 100/**
101 * Our workers
102 */
103static pthread_t * worker;
104
105/**
106 * Lock for the open jobs queue.
107 */
108static pthread_mutex_t jobs_lock;
109
110/**
111 * Lock for the finished results queue.
112 */
113static pthread_mutex_t results_lock;
114
115/**
116 * Wait condition on new jobs
117 */
118static pthread_cond_t empty_jobs;
119
120/**
121 * For threads to know we are shutting down
122 */
123static int in_shutdown = GNUNET_NO;
124
125/**
126 * Our notification pipe
127 */
128static struct GNUNET_DISK_PipeHandle *notification_pipe;
129
130/**
131 * Pipe read task
132 */
133static struct GNUNET_SCHEDULER_Task *pipe_read_task;
134
135struct OpenSignJob
136{
137
138 struct OpenSignJob *next;
139
140 struct OpenSignJob *prev;
141
142 struct GNUNET_IDENTITY_PrivateKey zone;
143
144 struct GNUNET_GNSRECORD_Block *block;
145
146 struct GNUNET_GNSRECORD_Block *block_priv;
147
148 struct DhtPutActivity *ma;
149
150 size_t block_size;
151
152 struct GNUNET_TIME_Absolute expire_pub;
153
154 char *label;
155
156};
157
158
159/**
160 * DLL
161 */
162static struct OpenSignJob *jobs_head;
163
164/**
165 * DLL
166 */
167static struct OpenSignJob *jobs_tail;
168
169/**
170 * DLL
171 */
172static struct OpenSignJob *results_head;
173
174/**
175 * DLL
176 */
177static struct OpenSignJob *results_tail;
178
179
180/**
94 * Handle for DHT PUT activity triggered from the namestore monitor. 181 * Handle for DHT PUT activity triggered from the namestore monitor.
95 */ 182 */
96struct DhtPutActivity 183struct DhtPutActivity
@@ -155,6 +242,11 @@ static struct GNUNET_DHT_Handle *dht_handle;
155static struct GNUNET_NAMESTORE_Handle *namestore_handle; 242static struct GNUNET_NAMESTORE_Handle *namestore_handle;
156 243
157/** 244/**
245 * Handle to monitor namestore changes to instant propagation.
246 */
247static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
248
249/**
158 * Our handle to the namecache service 250 * Our handle to the namecache service
159 */ 251 */
160static struct GNUNET_NAMECACHE_Handle *namecache; 252static struct GNUNET_NAMECACHE_Handle *namecache;
@@ -280,6 +372,17 @@ static struct CacheOperation *cop_head;
280static struct CacheOperation *cop_tail; 372static struct CacheOperation *cop_tail;
281 373
282 374
375static void
376free_job (struct OpenSignJob *job)
377{
378 if (job->block != job->block_priv)
379 GNUNET_free (job->block_priv);
380 GNUNET_free (job->block);
381 if (NULL != job->label)
382 GNUNET_free (job->label);
383 GNUNET_free (job);
384}
385
283/** 386/**
284 * Task run during shutdown. 387 * Task run during shutdown.
285 * 388 *
@@ -291,10 +394,16 @@ shutdown_task (void *cls)
291{ 394{
292 struct DhtPutActivity *ma; 395 struct DhtPutActivity *ma;
293 struct CacheOperation *cop; 396 struct CacheOperation *cop;
397 struct OpenSignJob *job;
294 398
295 (void) cls; 399 (void) cls;
400 in_shutdown = GNUNET_YES;
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
297 "Shutting down!\n"); 402 "Shutting down!\n");
403 if (NULL != notification_pipe)
404 GNUNET_DISK_pipe_close (notification_pipe);
405 if (NULL != pipe_read_task)
406 GNUNET_SCHEDULER_cancel (pipe_read_task);
298 while (NULL != (cop = cop_head)) 407 while (NULL != (cop = cop_head))
299 { 408 {
300 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 409 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -303,11 +412,29 @@ shutdown_task (void *cls)
303 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 412 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
304 GNUNET_free (cop); 413 GNUNET_free (cop);
305 } 414 }
415 GNUNET_assert (0 == pthread_mutex_lock (&jobs_lock));
416 while (NULL != (job = jobs_head))
417 {
418 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
419 "Removing incomplete jobs\n");
420 GNUNET_CONTAINER_DLL_remove (jobs_head, jobs_tail, job);
421 free_job (job);
422 }
423 GNUNET_assert (0 == pthread_mutex_unlock (&jobs_lock));
424 GNUNET_assert (0 == pthread_mutex_lock (&results_lock));
425 while (NULL != (job = results_head))
426 {
427 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
428 "Removing incomplete jobs\n");
429 GNUNET_CONTAINER_DLL_remove (results_head, results_tail, job);
430 free_job (job);
431 }
432 GNUNET_assert (0 == pthread_mutex_unlock (&results_lock));
306 433
307 while (NULL != (ma = it_head)) 434 while (NULL != (ma = it_head))
308 { 435 {
309 GNUNET_DHT_put_cancel (ma->ph); 436 if (NULL != ma->ph)
310 dht_queue_length--; 437 GNUNET_DHT_put_cancel (ma->ph);
311 GNUNET_CONTAINER_DLL_remove (it_head, 438 GNUNET_CONTAINER_DLL_remove (it_head,
312 it_tail, 439 it_tail,
313 ma); 440 ma);
@@ -330,6 +457,11 @@ shutdown_task (void *cls)
330 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter); 457 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
331 namestore_iter = NULL; 458 namestore_iter = NULL;
332 } 459 }
460 if (NULL != zmon)
461 {
462 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
463 zmon = NULL;
464 }
333 if (NULL != namestore_handle) 465 if (NULL != namestore_handle)
334 { 466 {
335 GNUNET_NAMESTORE_disconnect (namestore_handle); 467 GNUNET_NAMESTORE_disconnect (namestore_handle);
@@ -340,13 +472,14 @@ shutdown_task (void *cls)
340 GNUNET_NAMECACHE_disconnect (namecache); 472 GNUNET_NAMECACHE_disconnect (namecache);
341 namecache = NULL; 473 namecache = NULL;
342 } 474 }
343if (NULL != dht_handle) 475 if (NULL != dht_handle)
344 { 476 {
345 GNUNET_DHT_disconnect (dht_handle); 477 GNUNET_DHT_disconnect (dht_handle);
346 dht_handle = NULL; 478 dht_handle = NULL;
347 } 479 }
348} 480}
349 481
482
350/** 483/**
351 * Cache operation complete, clean up. 484 * Cache operation complete, clean up.
352 * 485 *
@@ -406,7 +539,6 @@ refresh_block (const struct GNUNET_GNSRECORD_Block *block)
406} 539}
407 540
408 541
409
410/** 542/**
411 * Method called periodically that triggers iteration over authoritative records 543 * Method called periodically that triggers iteration over authoritative records
412 * 544 *
@@ -643,7 +775,6 @@ dht_put_continuation (void *cls)
643} 775}
644 776
645 777
646
647/** 778/**
648 * Store GNS records in the DHT. 779 * Store GNS records in the DHT.
649 * 780 *
@@ -654,7 +785,7 @@ dht_put_continuation (void *cls)
654 * @param ma handle for the put operation 785 * @param ma handle for the put operation
655 * @return DHT PUT handle, NULL on error 786 * @return DHT PUT handle, NULL on error
656 */ 787 */
657static struct GNUNET_DHT_PutHandle * 788static void
658perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key, 789perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
659 const char *label, 790 const char *label,
660 const struct GNUNET_GNSRECORD_Data *rd, 791 const struct GNUNET_GNSRECORD_Data *rd,
@@ -665,11 +796,9 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
665 struct GNUNET_GNSRECORD_Data rd_public[rd_count]; 796 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
666 struct GNUNET_GNSRECORD_Block *block; 797 struct GNUNET_GNSRECORD_Block *block;
667 struct GNUNET_GNSRECORD_Block *block_priv; 798 struct GNUNET_GNSRECORD_Block *block_priv;
668 struct GNUNET_HashCode query; 799 struct GNUNET_TIME_Absolute expire_pub;
669 struct GNUNET_TIME_Absolute expire_priv;
670 size_t block_size; 800 size_t block_size;
671 unsigned int rd_public_count = 0; 801 unsigned int rd_public_count = 0;
672 struct GNUNET_DHT_PutHandle *ret;
673 char *emsg; 802 char *emsg;
674 803
675 if (GNUNET_OK != 804 if (GNUNET_OK !=
@@ -678,7 +807,7 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
678 rd_count, 807 rd_count,
679 rd_public, 808 rd_public,
680 &rd_public_count, 809 &rd_public_count,
681 &expire_priv, 810 &expire_pub,
682 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE, 811 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE,
683 &emsg)) 812 &emsg))
684 { 813 {
@@ -687,68 +816,120 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
687 GNUNET_free (emsg); 816 GNUNET_free (emsg);
688 } 817 }
689 818
690 if (cache_keys) 819 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create_unsigned (key,
691 { 820 expire_pub,
692 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key, 821 label,
693 expire, 822 rd_public,
694 label, 823 rd_public_count,
695 rd_public, 824 &block));
696 rd_public_count,
697 &block));
698 }
699 else
700 {
701 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
702 expire,
703 label,
704 rd_public,
705 rd_public_count,
706 &block));
707 }
708 if (NULL == block) 825 if (NULL == block)
709 { 826 {
710 GNUNET_break (0); 827 GNUNET_break (0);
711 return NULL; /* whoops */ 828 return; /* whoops */
712 } 829 }
713 if (rd_count != rd_public_count) 830 if (rd_count != rd_public_count)
714 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key, 831 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create_unsigned (key,
715 expire_priv, 832 expire,
716 label, 833 label,
717 rd, 834 rd,
718 rd_count, 835 rd_count,
719 &block_priv)); 836 &
837 block_priv));
720 else 838 else
721 block_priv = block; 839 block_priv = block;
722 block_size = GNUNET_GNSRECORD_block_get_size (block); 840 block_size = GNUNET_GNSRECORD_block_get_size (block);
723 GNUNET_GNSRECORD_query_from_private_key (key, 841 GNUNET_assert (0 == pthread_mutex_lock (&jobs_lock));
724 label, 842 struct OpenSignJob *job = GNUNET_new (struct OpenSignJob);
725 &query); 843 job->block = block;
726 GNUNET_STATISTICS_update (statistics, 844 job->block_size = block_size;
727 "DHT put operations initiated", 845 job->block_priv = block_priv;
728 1, 846 job->zone = *key;
729 GNUNET_NO); 847 job->ma = ma;
848 job->label = GNUNET_strdup (label);
849 job->expire_pub = expire_pub;
850 GNUNET_CONTAINER_DLL_insert (jobs_head, jobs_tail, job);
851 GNUNET_assert (0 == pthread_cond_signal (&empty_jobs));
852 GNUNET_assert (0 == pthread_mutex_unlock (&jobs_lock));
730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
731 "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n", 854 "Creating job with %u record(s) for label `%s', expiration `%s'\n",
732 rd_public_count, 855 rd_public_count,
733 label, 856 label,
734 GNUNET_STRINGS_absolute_time_to_string (expire), 857 GNUNET_STRINGS_absolute_time_to_string (expire));
735 GNUNET_h2s (&query));
736 num_public_records++; 858 num_public_records++;
737 ret = GNUNET_DHT_put (dht_handle, 859 return;
738 &query, 860}
739 DHT_GNS_REPLICATION_LEVEL, 861
740 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, 862
741 GNUNET_BLOCK_TYPE_GNS_NAMERECORD, 863static void
742 block_size, 864notification_pipe_cb (void *cls);
743 block, 865
744 expire, 866static void
745 &dht_put_continuation, 867initiate_put_from_pipe_trigger (void *cls)
746 ma); 868{
747 refresh_block (block_priv); 869 struct GNUNET_HashCode query;
748 if (block != block_priv) 870 struct OpenSignJob *job;
749 GNUNET_free (block_priv); 871 const struct GNUNET_DISK_FileHandle *np_fh;
750 GNUNET_free (block); 872 char buf[100];
751 return ret; 873 ssize_t nf_count;
874
875 pipe_read_task = NULL;
876 np_fh = GNUNET_DISK_pipe_handle (notification_pipe,
877 GNUNET_DISK_PIPE_END_READ);
878 pipe_read_task =
879 GNUNET_SCHEDULER_add_read_file (
880 GNUNET_TIME_UNIT_FOREVER_REL,
881 np_fh,
882 notification_pipe_cb,
883 NULL);
884 /* empty queue */
885 nf_count = GNUNET_DISK_file_read (np_fh, buf, sizeof (buf));
886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %lld notifications from pipe\n",
887 (long long) nf_count);
888 while (true)
889 {
890 GNUNET_assert (0 == pthread_mutex_lock (&results_lock));
891 if (NULL == results_head)
892 {
893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
894 "No more results. Back to sleep.\n");
895 GNUNET_assert (0 == pthread_mutex_unlock (&results_lock));
896 return;
897 }
898 job = results_head;
899 GNUNET_CONTAINER_DLL_remove (results_head, results_tail, job);
900 GNUNET_assert (0 == pthread_mutex_unlock (&results_lock));
901 GNUNET_GNSRECORD_query_from_private_key (&job->zone,
902 job->label,
903 &query);
904 GNUNET_STATISTICS_update (statistics,
905 "DHT put operations initiated",
906 1,
907 GNUNET_NO);
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
909 "Storing record(s) for label `%s' in DHT under key %s\n",
910 job->label,
911 GNUNET_h2s (&query));
912 job->ma->ph = GNUNET_DHT_put (dht_handle,
913 &query,
914 DHT_GNS_REPLICATION_LEVEL,
915 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
916 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
917 job->block_size,
918 job->block,
919 job->expire_pub,
920 &dht_put_continuation,
921 job->ma);
922 if (NULL == job->ma->ph)
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
925 "Could not perform DHT PUT, is the DHT running?\n");
926 GNUNET_free (job->ma);
927 free_job (job);
928 return;
929 }
930 refresh_block (job->block_priv);
931 free_job (job);
932 }
752} 933}
753 934
754 935
@@ -823,6 +1004,7 @@ zone_iteration_finished (void *cls)
823 } 1004 }
824} 1005}
825 1006
1007
826/** 1008/**
827 * Function used to put all records successively into the DHT. 1009 * Function used to put all records successively into the DHT.
828 * 1010 *
@@ -867,47 +1049,32 @@ put_gns_record (void *cls,
867 /* We got a set of records to publish */ 1049 /* We got a set of records to publish */
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
869 "Starting DHT PUT\n"); 1051 "Starting DHT PUT\n");
870
871 ma = GNUNET_new (struct DhtPutActivity);
872 ma->start_date = GNUNET_TIME_absolute_get ();
873 ma->ph = perform_dht_put (key,
874 label,
875 rd,
876 rd_count,
877 expire,
878 ma);
879 put_cnt++; 1052 put_cnt++;
880 if (0 == put_cnt % DELTA_INTERVAL) 1053 if (0 == put_cnt % DELTA_INTERVAL)
881 update_velocity (DELTA_INTERVAL); 1054 update_velocity (DELTA_INTERVAL);
882 check_zone_namestore_next (); 1055 check_zone_namestore_next ();
883 if (NULL == ma->ph) 1056 if (dht_queue_length >= DHT_QUEUE_LIMIT)
884 { 1057 {
885 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1058 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
886 "Could not perform DHT PUT, is the DHT running?\n"); 1059 "DHT PUT queue length exceeded (%u), aborting PUT\n",
887 GNUNET_free (ma); 1060 DHT_QUEUE_LIMIT);
888 return; 1061 return;
889 } 1062 }
1063
1064 ma = GNUNET_new (struct DhtPutActivity);
1065 perform_dht_put (key,
1066 label,
1067 rd,
1068 rd_count,
1069 expire,
1070 ma);
890 dht_queue_length++; 1071 dht_queue_length++;
891 GNUNET_CONTAINER_DLL_insert_tail (it_head, 1072 GNUNET_CONTAINER_DLL_insert_tail (it_head,
892 it_tail, 1073 it_tail,
893 ma); 1074 ma);
894 if (dht_queue_length > DHT_QUEUE_LIMIT)
895 {
896 ma = it_head;
897 GNUNET_CONTAINER_DLL_remove (it_head,
898 it_tail,
899 ma);
900 GNUNET_DHT_put_cancel (ma->ph);
901 dht_queue_length--;
902 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
903 "DHT PUT unconfirmed after %s, aborting PUT\n",
904 GNUNET_STRINGS_relative_time_to_string (
905 GNUNET_TIME_absolute_get_duration (ma->start_date),
906 GNUNET_YES));
907 GNUNET_free (ma);
908 }
909} 1075}
910 1076
1077
911/** 1078/**
912 * Periodically iterate over all zones and store everything in DHT 1079 * Periodically iterate over all zones and store everything in DHT
913 * 1080 *
@@ -943,6 +1110,206 @@ publish_zone_dht_start (void *cls)
943 1110
944 1111
945/** 1112/**
1113 * Store GNS records in the DHT.
1114 *
1115 * @param key key of the zone
1116 * @param label label to store under
1117 * @param rd_public public record data
1118 * @param rd_public_count number of records in @a rd_public
1119 * @param ma handle for the PUT operation
1120 * @return DHT PUT handle, NULL on error
1121 */
1122static void
1123perform_dht_put_monitor (const struct GNUNET_IDENTITY_PrivateKey *key,
1124 const char *label,
1125 const struct GNUNET_GNSRECORD_Data *rd,
1126 unsigned int rd_count,
1127 struct GNUNET_TIME_Absolute expire,
1128 struct DhtPutActivity *ma)
1129{
1130 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
1131 struct GNUNET_GNSRECORD_Block *block;
1132 struct GNUNET_GNSRECORD_Block *block_priv;
1133 struct GNUNET_TIME_Absolute expire_pub;
1134 size_t block_size;
1135 unsigned int rd_public_count = 0;
1136 char *emsg;
1137
1138 if (GNUNET_OK !=
1139 GNUNET_GNSRECORD_normalize_record_set (label,
1140 rd,
1141 rd_count,
1142 rd_public,
1143 &rd_public_count,
1144 &expire_pub,
1145 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE,
1146 &emsg))
1147 {
1148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1149 "%s\n", emsg);
1150 GNUNET_free (emsg);
1151 }
1152
1153 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create_unsigned (key,
1154 expire_pub,
1155 label,
1156 rd_public,
1157 rd_public_count,
1158 &block));
1159 if (NULL == block)
1160 {
1161 GNUNET_break (0);
1162 return; /* whoops */
1163 }
1164 if (rd_count != rd_public_count)
1165 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create_unsigned (key,
1166 expire,
1167 label,
1168 rd,
1169 rd_count,
1170 &
1171 block_priv));
1172 else
1173 block_priv = block;
1174 block_size = GNUNET_GNSRECORD_block_get_size (block);
1175 GNUNET_assert (0 == pthread_mutex_lock (&jobs_lock));
1176 struct OpenSignJob *job = GNUNET_new (struct OpenSignJob);
1177 job->block = block;
1178 job->block_size = block_size;
1179 job->block_priv = block_priv;
1180 job->zone = *key;
1181 job->ma = ma;
1182 job->label = GNUNET_strdup (label);
1183 job->expire_pub = expire_pub;
1184 GNUNET_CONTAINER_DLL_insert (jobs_head, jobs_tail, job);
1185 GNUNET_assert (0 == pthread_cond_signal (&empty_jobs));
1186 GNUNET_assert (0 == pthread_mutex_unlock (&jobs_lock));
1187}
1188
1189
1190/**
1191 * Process a record that was stored in the namestore
1192 * (invoked by the monitor).
1193 *
1194 * @param cls closure, NULL
1195 * @param zone private key of the zone; NULL on disconnect
1196 * @param label label of the records; NULL on disconnect
1197 * @param rd_count number of entries in @a rd array, 0 if label was deleted
1198 * @param rd array of records with data to store
1199 * @param expire expiration of this record set
1200 */
1201static void
1202handle_monitor_event (void *cls,
1203 const struct GNUNET_IDENTITY_PrivateKey *zone,
1204 const char *label,
1205 unsigned int rd_count,
1206 const struct GNUNET_GNSRECORD_Data *rd,
1207 struct GNUNET_TIME_Absolute expire)
1208{
1209 struct DhtPutActivity *ma;
1210
1211 (void) cls;
1212 GNUNET_STATISTICS_update (statistics,
1213 "Namestore monitor events received",
1214 1,
1215 GNUNET_NO);
1216 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1217 "Received %u records for label `%s' via namestore monitor\n",
1218 rd_count,
1219 label);
1220 if (0 == rd_count)
1221 {
1222 GNUNET_NAMESTORE_zone_monitor_next (zmon,
1223 1);
1224 return; /* nothing to do */
1225 }
1226 if (dht_queue_length >= DHT_QUEUE_LIMIT)
1227 {
1228 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1229 "DHT PUT queue length exceeded (%u), aborting PUT\n",
1230 DHT_QUEUE_LIMIT);
1231 return;
1232 }
1233 ma = GNUNET_new (struct DhtPutActivity);
1234 perform_dht_put_monitor (zone,
1235 label,
1236 rd,
1237 rd_count,
1238 expire,
1239 ma);
1240 GNUNET_NAMESTORE_zone_monitor_next (zmon,
1241 1);
1242 GNUNET_CONTAINER_DLL_insert_tail (it_head,
1243 it_tail,
1244 ma);
1245 dht_queue_length++;
1246}
1247
1248
1249/**
1250 * The zone monitor encountered an IPC error trying to to get in
1251 * sync. Restart from the beginning.
1252 *
1253 * @param cls NULL
1254 */
1255static void
1256handle_monitor_error (void *cls)
1257{
1258 (void) cls;
1259 GNUNET_STATISTICS_update (statistics,
1260 "Namestore monitor errors encountered",
1261 1,
1262 GNUNET_NO);
1263}
1264
1265
1266static void*
1267sign_worker (void *cls)
1268{
1269 struct OpenSignJob *job;
1270 const struct GNUNET_DISK_FileHandle *fh;
1271
1272 fh = GNUNET_DISK_pipe_handle (notification_pipe, GNUNET_DISK_PIPE_END_WRITE);
1273 while (GNUNET_YES != in_shutdown)
1274 {
1275 GNUNET_assert (0 == pthread_mutex_lock (&jobs_lock));
1276 while (NULL == jobs_head)
1277 GNUNET_assert (0 == pthread_cond_wait (&empty_jobs, &jobs_lock));
1278 if (GNUNET_YES == in_shutdown)
1279 {
1280 GNUNET_assert (0 == pthread_mutex_unlock (&jobs_lock));
1281 return NULL;
1282 }
1283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1284 "Taking on Job for %s\n", jobs_head->label);
1285 job = jobs_head;
1286 GNUNET_CONTAINER_DLL_remove (jobs_head, jobs_tail, job);
1287 GNUNET_assert (0 == pthread_mutex_unlock (&jobs_lock));
1288 GNUNET_GNSRECORD_block_sign (&job->zone, job->label, job->block);
1289 if (job->block != job->block_priv)
1290 GNUNET_GNSRECORD_block_sign (&job->zone, job->label, job->block_priv);
1291 GNUNET_assert (0 == pthread_mutex_lock (&results_lock));
1292 GNUNET_CONTAINER_DLL_insert (results_head, results_tail, job);
1293 GNUNET_assert (0 == pthread_mutex_unlock (&results_lock));
1294 job = NULL;
1295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1296 "Done, notifying main thread through pipe!\n");
1297 GNUNET_DISK_file_write (fh, "!", 1);
1298 }
1299 return NULL;
1300}
1301
1302
1303static void
1304notification_pipe_cb (void *cls)
1305{
1306 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1307 "Received wake up notification through pipe, checking results\n");
1308 GNUNET_SCHEDULER_add_now (&initiate_put_from_pipe_trigger, NULL);
1309}
1310
1311
1312/**
946 * Perform zonemaster duties: watch namestore, publish records. 1313 * Perform zonemaster duties: watch namestore, publish records.
947 * 1314 *
948 * @param cls closure 1315 * @param cls closure
@@ -1034,8 +1401,56 @@ run (void *cls,
1034 GNUNET_NO); 1401 GNUNET_NO);
1035 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, 1402 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
1036 NULL); 1403 NULL);
1404 zmon = GNUNET_NAMESTORE_zone_monitor_start2 (c,
1405 NULL,
1406 GNUNET_NO,
1407 &handle_monitor_error,
1408 NULL,
1409 &handle_monitor_event,
1410 NULL,
1411 NULL /* sync_cb */,
1412 NULL,
1413 GNUNET_GNSRECORD_FILTER_NONE);
1414 GNUNET_NAMESTORE_zone_monitor_next (zmon,
1415 NAMESTORE_MONITOR_QUEUE_LIMIT - 1);
1416 GNUNET_break (NULL != zmon);
1417
1037 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1418 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1038 NULL); 1419 NULL);
1420
1421 notification_pipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
1422 const struct GNUNET_DISK_FileHandle *np_fh = GNUNET_DISK_pipe_handle (
1423 notification_pipe,
1424 GNUNET_DISK_PIPE_END_READ);
1425 pipe_read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1426 np_fh,
1427 notification_pipe_cb, NULL);
1428
1429 long long unsigned int worker_count = 1;
1430 if (GNUNET_OK !=
1431 GNUNET_CONFIGURATION_get_value_number (c,
1432 "zonemaster",
1433 "WORKER_COUNT",
1434 &worker_count))
1435 {
1436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1437 "Number of workers not defined falling back to 1\n");
1438 }
1439 worker = GNUNET_malloc (sizeof (pthread_t) * worker_count);
1440 /** Start worker */
1441 for (int i = 0; i < worker_count; i++)
1442 {
1443 if (0 !=
1444 pthread_create (&worker[i],
1445 NULL,
1446 &sign_worker,
1447 NULL))
1448 {
1449 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1450 "pthread_create");
1451 GNUNET_SCHEDULER_shutdown ();
1452 }
1453 }
1039} 1454}
1040 1455
1041 1456
diff --git a/src/zonemaster/zonemaster.conf.in b/src/zonemaster/zonemaster.conf.in
index 315388417..549394d6c 100644
--- a/src/zonemaster/zonemaster.conf.in
+++ b/src/zonemaster/zonemaster.conf.in
@@ -6,6 +6,7 @@ HOSTNAME = localhost
6BINARY = gnunet-service-zonemaster 6BINARY = gnunet-service-zonemaster
7UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock 7UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock
8@JAVAPORT@PORT = 2123 8@JAVAPORT@PORT = 2123
9WORKER_COUNT = 4
9 10
10# Do we require users that want to access GNS to run this process 11# Do we require users that want to access GNS to run this process
11# (usually not a good idea) 12# (usually not a good idea)
@@ -24,21 +25,3 @@ ZONE_PUBLISH_TIME_WINDOW = 4 h
24# USE_CACHE = YES 25# USE_CACHE = YES
25 26
26# PREFIX = valgrind --leak-check=full --track-origins=yes 27# 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