diff options
author | t3sserakt <t3ss@posteo.de> | 2022-10-25 09:59:23 +0200 |
---|---|---|
committer | t3sserakt <t3ss@posteo.de> | 2022-10-25 10:02:01 +0200 |
commit | b3a76100568e15660211945d931173f858156169 (patch) | |
tree | 54d89d7a0b743df81b5df095f60c3f13c016c69d /src/zonemaster | |
parent | c5f3eb40c97b2bcad7537607ca870a925aa9bed8 (diff) | |
parent | fa48dbb242415a8dc06465863054b8d61c0e26bb (diff) | |
download | gnunet-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.am | 19 | ||||
-rw-r--r-- | src/zonemaster/gnunet-service-zonemaster-monitor.c | 612 | ||||
-rw-r--r-- | src/zonemaster/gnunet-service-zonemaster.c | 589 | ||||
-rw-r--r-- | src/zonemaster/zonemaster.conf.in | 19 |
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 | |||
16 | endif | 16 | endif |
17 | 17 | ||
18 | libexec_PROGRAMS = \ | 18 | libexec_PROGRAMS = \ |
19 | gnunet-service-zonemaster \ | 19 | gnunet-service-zonemaster |
20 | gnunet-service-zonemaster-monitor | ||
21 | 20 | ||
22 | gnunet_service_zonemaster_SOURCES = \ | 21 | gnunet_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 | |||
35 | gnunet_service_zonemaster_monitor_SOURCES = \ | ||
36 | gnunet-service-zonemaster-monitor.c | ||
37 | gnunet_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 | */ | ||
64 | struct 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 | */ | ||
90 | struct 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 | */ | ||
113 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
114 | |||
115 | /** | ||
116 | * Our handle to the DHT | ||
117 | */ | ||
118 | static struct GNUNET_DHT_Handle *dht_handle; | ||
119 | |||
120 | /** | ||
121 | * Our handle to the namestore service | ||
122 | */ | ||
123 | static struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
124 | |||
125 | /** | ||
126 | * Handle to monitor namestore changes to instant propagation. | ||
127 | */ | ||
128 | static struct GNUNET_NAMESTORE_ZoneMonitor *zmon; | ||
129 | |||
130 | /** | ||
131 | * Head of monitor activities; kept in a DLL. | ||
132 | */ | ||
133 | static struct DhtPutActivity *ma_head; | ||
134 | |||
135 | /** | ||
136 | * Tail of monitor activities; kept in a DLL. | ||
137 | */ | ||
138 | static struct DhtPutActivity *ma_tail; | ||
139 | |||
140 | /** | ||
141 | * Our handle to the namecache service | ||
142 | */ | ||
143 | static struct GNUNET_NAMECACHE_Handle *namecache; | ||
144 | |||
145 | /** | ||
146 | * Use the namecache? Doing so creates additional cryptographic | ||
147 | * operations whenever we touch a record. | ||
148 | */ | ||
149 | static int disable_namecache; | ||
150 | |||
151 | |||
152 | /** | ||
153 | * Number of entries in the DHT queue #ma_head. | ||
154 | */ | ||
155 | static unsigned int ma_queue_length; | ||
156 | |||
157 | /** | ||
158 | * Optimize block insertion by caching map of private keys to | ||
159 | * public keys in memory? | ||
160 | */ | ||
161 | static int cache_keys; | ||
162 | |||
163 | /** | ||
164 | * Head of cop DLL. | ||
165 | */ | ||
166 | static struct CacheOperation *cop_head; | ||
167 | |||
168 | /** | ||
169 | * Tail of cop DLL. | ||
170 | */ | ||
171 | static struct CacheOperation *cop_tail; | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Task run during shutdown. | ||
176 | * | ||
177 | * @param cls unused | ||
178 | * @param tc unused | ||
179 | */ | ||
180 | static void | ||
181 | shutdown_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 | */ | ||
242 | static void | ||
243 | finish_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 | */ | ||
266 | static void | ||
267 | refresh_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 | */ | ||
301 | static void | ||
302 | dht_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 | */ | ||
326 | static struct GNUNET_DHT_PutHandle * | ||
327 | perform_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 | */ | ||
429 | static void | ||
430 | handle_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 | */ | ||
498 | static void | ||
499 | handle_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 | */ | ||
516 | static void | ||
517 | run (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 | */ | ||
602 | GNUNET_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 | */ | ||
103 | static pthread_t * worker; | ||
104 | |||
105 | /** | ||
106 | * Lock for the open jobs queue. | ||
107 | */ | ||
108 | static pthread_mutex_t jobs_lock; | ||
109 | |||
110 | /** | ||
111 | * Lock for the finished results queue. | ||
112 | */ | ||
113 | static pthread_mutex_t results_lock; | ||
114 | |||
115 | /** | ||
116 | * Wait condition on new jobs | ||
117 | */ | ||
118 | static pthread_cond_t empty_jobs; | ||
119 | |||
120 | /** | ||
121 | * For threads to know we are shutting down | ||
122 | */ | ||
123 | static int in_shutdown = GNUNET_NO; | ||
124 | |||
125 | /** | ||
126 | * Our notification pipe | ||
127 | */ | ||
128 | static struct GNUNET_DISK_PipeHandle *notification_pipe; | ||
129 | |||
130 | /** | ||
131 | * Pipe read task | ||
132 | */ | ||
133 | static struct GNUNET_SCHEDULER_Task *pipe_read_task; | ||
134 | |||
135 | struct 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 | */ | ||
162 | static struct OpenSignJob *jobs_head; | ||
163 | |||
164 | /** | ||
165 | * DLL | ||
166 | */ | ||
167 | static struct OpenSignJob *jobs_tail; | ||
168 | |||
169 | /** | ||
170 | * DLL | ||
171 | */ | ||
172 | static struct OpenSignJob *results_head; | ||
173 | |||
174 | /** | ||
175 | * DLL | ||
176 | */ | ||
177 | static 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 | */ |
96 | struct DhtPutActivity | 183 | struct DhtPutActivity |
@@ -155,6 +242,11 @@ static struct GNUNET_DHT_Handle *dht_handle; | |||
155 | static struct GNUNET_NAMESTORE_Handle *namestore_handle; | 242 | static struct GNUNET_NAMESTORE_Handle *namestore_handle; |
156 | 243 | ||
157 | /** | 244 | /** |
245 | * Handle to monitor namestore changes to instant propagation. | ||
246 | */ | ||
247 | static struct GNUNET_NAMESTORE_ZoneMonitor *zmon; | ||
248 | |||
249 | /** | ||
158 | * Our handle to the namecache service | 250 | * Our handle to the namecache service |
159 | */ | 251 | */ |
160 | static struct GNUNET_NAMECACHE_Handle *namecache; | 252 | static struct GNUNET_NAMECACHE_Handle *namecache; |
@@ -280,6 +372,17 @@ static struct CacheOperation *cop_head; | |||
280 | static struct CacheOperation *cop_tail; | 372 | static struct CacheOperation *cop_tail; |
281 | 373 | ||
282 | 374 | ||
375 | static void | ||
376 | free_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 | } |
343 | if (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 | */ |
657 | static struct GNUNET_DHT_PutHandle * | 788 | static void |
658 | perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key, | 789 | perform_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, | 863 | static void |
742 | block_size, | 864 | notification_pipe_cb (void *cls); |
743 | block, | 865 | |
744 | expire, | 866 | static void |
745 | &dht_put_continuation, | 867 | initiate_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 | */ | ||
1122 | static void | ||
1123 | perform_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 | */ | ||
1201 | static void | ||
1202 | handle_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 | */ | ||
1255 | static void | ||
1256 | handle_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 | |||
1266 | static void* | ||
1267 | sign_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 | |||
1303 | static void | ||
1304 | notification_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 | |||
6 | BINARY = gnunet-service-zonemaster | 6 | BINARY = gnunet-service-zonemaster |
7 | UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock | 7 | UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock |
8 | @JAVAPORT@PORT = 2123 | 8 | @JAVAPORT@PORT = 2123 |
9 | WORKER_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] | ||
31 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
32 | RUN_PER_USER = YES | ||
33 | IMMEDIATE_START = YES | ||
34 | HOSTNAME = localhost | ||
35 | BINARY = gnunet-service-zonemaster-monitor | ||
36 | UNIXPATH = $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) | ||
41 | UNIX_MATCH_UID = NO | ||
42 | |||
43 | # Do we require users that want to access GNS to be in the 'gnunet' group? | ||
44 | UNIX_MATCH_GID = NO | ||