GNUnet  0.11.x
gnunet-service-zonemaster-monitor.c
Go to the documentation of this file.
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 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_dht_service.h"
31 
32 
33 #define LOG_STRERROR_FILE(kind, syscall, \
34  filename) GNUNET_log_from_strerror_file (kind, "util", \
35  syscall, \
36  filename)
37 
38 
43 #define PUBLISH_OPS_PER_EXPIRATION 4
44 
48 #define DHT_QUEUE_LIMIT 2000
49 
54 #define NAMESTORE_QUEUE_LIMIT 5
55 
59 #define DHT_GNS_REPLICATION_LEVEL 5
60 
61 
66 {
71 
76 
81 
86 };
87 
88 
93 
98 
103 
108 
112 static struct DhtPutActivity *ma_head;
113 
117 static struct DhtPutActivity *ma_tail;
118 
122 static unsigned int ma_queue_length;
123 
128 static int cache_keys;
129 
130 
137 static void
138 shutdown_task (void *cls)
139 {
140  struct DhtPutActivity *ma;
141 
142  (void) cls;
144  "Shutting down!\n");
145  while (NULL != (ma = ma_head))
146  {
148  ma_queue_length--;
150  ma_tail,
151  ma);
152  GNUNET_free (ma);
153  }
154  if (NULL != statistics)
155  {
156  GNUNET_STATISTICS_destroy (statistics,
157  GNUNET_NO);
158  statistics = NULL;
159  }
160  if (NULL != zmon)
161  {
163  zmon = NULL;
164  }
165  if (NULL != namestore_handle)
166  {
167  GNUNET_NAMESTORE_disconnect (namestore_handle);
168  namestore_handle = NULL;
169  }
170  if (NULL != dht_handle)
171  {
172  GNUNET_DHT_disconnect (dht_handle);
173  dht_handle = NULL;
174  }
175 }
176 
177 
184 static void
186 {
187  struct DhtPutActivity *ma = cls;
188 
190  1);
191  ma_queue_length--;
193  ma_tail,
194  ma);
195  GNUNET_free (ma);
196 }
197 
198 
209 static unsigned int
211  unsigned int rd_count,
212  struct GNUNET_GNSRECORD_Data *rd_public)
213 {
214  struct GNUNET_TIME_Absolute now;
215  unsigned int rd_public_count;
216 
217  rd_public_count = 0;
218  now = GNUNET_TIME_absolute_get ();
219  for (unsigned int i = 0; i < rd_count; i++)
220  {
221  if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
222  continue;
223  if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
224  (rd[i].expiration_time < now.abs_value_us))
225  continue; /* record already expired, skip it */
226  rd_public[rd_public_count++] = rd[i];
227  }
228  return rd_public_count;
229 }
230 
231 
242 static struct GNUNET_DHT_PutHandle *
244  const char *label,
245  const struct GNUNET_GNSRECORD_Data *rd_public,
246  unsigned int rd_public_count,
247  struct DhtPutActivity *ma)
248 {
249  struct GNUNET_GNSRECORD_Block *block;
250  struct GNUNET_HashCode query;
251  struct GNUNET_TIME_Absolute expire;
252  size_t block_size;
253  struct GNUNET_DHT_PutHandle *ret;
254 
255  expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
256  rd_public);
257  if (cache_keys)
258  block = GNUNET_GNSRECORD_block_create2 (key,
259  expire,
260  label,
261  rd_public,
262  rd_public_count);
263  else
264  block = GNUNET_GNSRECORD_block_create (key,
265  expire,
266  label,
267  rd_public,
268  rd_public_count);
269  if (NULL == block)
270  {
271  GNUNET_break (0);
272  return NULL; /* whoops */
273  }
274  block_size = GNUNET_GNSRECORD_block_get_size (block);
276  label,
277  &query);
278  GNUNET_STATISTICS_update (statistics,
279  "DHT put operations initiated",
280  1,
281  GNUNET_NO);
283  "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
284  rd_public_count,
285  label,
287  GNUNET_h2s (&query));
288  ret = GNUNET_DHT_put (dht_handle,
289  &query,
293  block_size,
294  block,
295  expire,
297  ma);
298  GNUNET_free (block);
299  return ret;
300 }
301 
302 
313 static void
315  const struct GNUNET_IDENTITY_PrivateKey *zone,
316  const char *label,
317  unsigned int rd_count,
318  const struct GNUNET_GNSRECORD_Data *rd)
319 {
320  struct GNUNET_GNSRECORD_Data rd_public[rd_count];
321  unsigned int rd_public_count;
322  struct DhtPutActivity *ma;
323 
324  (void) cls;
325  GNUNET_STATISTICS_update (statistics,
326  "Namestore monitor events received",
327  1,
328  GNUNET_NO);
330  "Received %u records for label `%s' via namestore monitor\n",
331  rd_count,
332  label);
333  /* filter out records that are not public, and convert to
334  absolute expiration time. */
335  rd_public_count = convert_records_for_export (rd,
336  rd_count,
337  rd_public);
338  if (0 == rd_public_count)
339  {
341  1);
342  return; /* nothing to do */
343  }
344  ma = GNUNET_new (struct DhtPutActivity);
346  ma->ph = perform_dht_put (zone,
347  label,
348  rd,
349  rd_count,
350  ma);
351  if (NULL == ma->ph)
352  {
353  /* PUT failed, do not remember operation */
354  GNUNET_free (ma);
356  1);
357  return;
358  }
360  ma_tail,
361  ma);
362  ma_queue_length++;
364  {
365  ma = ma_head;
367  ma_tail,
368  ma);
370  ma_queue_length--;
372  "DHT PUT unconfirmed after %s, aborting PUT\n",
375  GNUNET_YES));
376  GNUNET_free (ma);
377  }
378 }
379 
380 
387 static void
389 {
390  (void) cls;
391  GNUNET_STATISTICS_update (statistics,
392  "Namestore monitor errors encountered",
393  1,
394  GNUNET_NO);
395 }
396 
397 
405 static void
406 run (void *cls,
407  const struct GNUNET_CONFIGURATION_Handle *c,
409 {
410  unsigned long long max_parallel_bg_queries = 128;
411 
412  (void) cls;
413  (void) service;
414  namestore_handle = GNUNET_NAMESTORE_connect (c);
415  if (NULL == namestore_handle)
416  {
418  _ ("Failed to connect to the namestore!\n"));
420  return;
421  }
423  "namestore",
424  "CACHE_KEYS");
425  if (GNUNET_OK ==
427  "zonemaster",
428  "MAX_PARALLEL_BACKGROUND_QUERIES",
429  &max_parallel_bg_queries))
430  {
432  "Number of allowed parallel background queries: %llu\n",
433  max_parallel_bg_queries);
434  }
435  if (0 == max_parallel_bg_queries)
436  max_parallel_bg_queries = 1;
437  dht_handle = GNUNET_DHT_connect (c,
438  (unsigned int) max_parallel_bg_queries);
439  if (NULL == dht_handle)
440  {
442  _ ("Could not connect to DHT!\n"));
444  NULL);
445  return;
446  }
447 
448  /* Schedule periodic put for our records. */
449  statistics = GNUNET_STATISTICS_create ("zonemaster-mon",
450  c);
452  NULL,
453  GNUNET_NO,
455  NULL,
457  NULL,
458  NULL /* sync_cb */,
459  NULL);
462  GNUNET_break (NULL != zmon);
464  NULL);
465 }
466 
467 
472  ("zonemaster-monitor",
474  &run,
475  NULL,
476  NULL,
477  NULL,
479 
480 
481 /* end of gnunet-service-zonemaster-monitor.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
struct GNUNET_DHT_PutHandle * ph
Handle for the DHT PUT operation.
struct DhtPutActivity * prev
Kept in a DLL.
static int cache_keys
Optimize block insertion by caching map of private keys to public keys in memory? ...
void GNUNET_DHT_put_cancel(struct GNUNET_DHT_PutHandle *ph)
Cancels a DHT PUT operation.
Definition: dht_api.c:1035
static void shutdown_task(void *cls)
Task run during shutdown.
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
static struct GNUNET_NAMESTORE_ZoneMonitor * zmon
Handle to monitor namestore changes to instant propagation.
Handle to a service.
Definition: service.c:116
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
struct GNUNET_NAMESTORE_ZoneMonitor * GNUNET_NAMESTORE_zone_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_PrivateKey *zone, int iterate_first, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor monitor, void *monitor_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls)
Begin monitoring a zone for changes.
struct GNUNET_TIME_Absolute start_date
When was this PUT initiated?
#define DHT_GNS_REPLICATION_LEVEL
What replication level do we use for DHT PUT operations?
A private key for an identity as per LSD0001.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_NAMESTORE_zone_monitor_stop(struct GNUNET_NAMESTORE_ZoneMonitor *zm)
Stop monitoring a zone for changes.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
Handle for the service.
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create(const struct GNUNET_IDENTITY_PrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records.
Handle for DHT PUT activity triggered from the namestore monitor.
Connection to the DHT service.
Definition: dht_api.c:201
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define DHT_QUEUE_LIMIT
How many pending DHT operations do we allow at most?
static void handle_monitor_event(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a record that was stored in the namestore (invoked by the monitor).
static char * zone
Name of the zone we manage.
static struct GNUNET_NAMESTORE_Handle * namestore_handle
Our handle to the namestore service.
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
Handle for a monitoring activity.
static void handle_monitor_error(void *cls)
The zone monitor encountered an IPC error trying to to get in sync.
GNUNET_SERVICE_MAIN("zonemaster-monitor", GNUNET_SERVICE_OPTION_NONE, &run, NULL, NULL, NULL, GNUNET_MQ_handler_end())
Define "main" method using service macro.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
Connection to the NAMESTORE service.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create2(const struct GNUNET_IDENTITY_PrivateKey *pkey, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records, cache derived public key (also keeps the private key in static memory...
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:702
static struct GNUNET_DHT_PutHandle * perform_dht_put(const struct GNUNET_IDENTITY_PrivateKey *key, const char *label, const struct GNUNET_GNSRECORD_Data *rd_public, unsigned int rd_public_count, struct DhtPutActivity *ma)
Store GNS records in the DHT.
This is a private record of this peer and it should thus not be handed out to other peers...
Block for storing record data.
A 512-bit hashcode.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Returns the expiration time of the given block of records.
struct GNUNET_HashCode key
The key used in the DHT.
struct GNUNET_DHT_PutHandle * GNUNET_DHT_put(struct GNUNET_DHT_Handle *handle, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, size_t size, const void *data, struct GNUNET_TIME_Absolute exp, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Perform a PUT operation storing data in the DHT.
Definition: dht_api.c:966
#define NAMESTORE_QUEUE_LIMIT
How many events may the namestore give us before it has to wait for us to keep up?
struct GNUNET_DHT_Handle * GNUNET_DHT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len)
Initialize the connection with the DHT service.
Definition: dht_api.c:890
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:918
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct DhtPutActivity * ma_head
Head of monitor activities; kept in a DLL.
void GNUNET_GNSRECORD_query_from_private_key(const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
Handle to a PUT request.
Definition: dht_api.c:43
static struct DhtPutActivity * ma_tail
Tail of monitor activities; kept in a DLL.
configuration data
Definition: configuration.c:84
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:263
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Perform zonemaster duties: watch namestore, publish records.
#define GNUNET_log(kind,...)
static struct GNUNET_DHT_Handle * dht_handle
Our handle to the DHT.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static unsigned int ma_queue_length
Number of entries in the DHT queue ma_head.
static unsigned int convert_records_for_export(const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *rd_public)
Convert namestore records from the internal format to that suitable for publication (removes private ...
Time for absolute times used by GNUnet, in microseconds.
static void dht_put_monitor_continuation(void *cls)
Continuation called from DHT once the PUT operation triggered by a monitor is done.
This expiration time of the record is a relative time (not an absolute time).
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:758
struct DhtPutActivity * next
Kept in a DLL.
void GNUNET_NAMESTORE_zone_monitor_next(struct GNUNET_NAMESTORE_ZoneMonitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_NAMESTORE_zone_monitor_start for the next record(s)...
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
Each peer along the way should look at &#39;enc&#39; (otherwise only the k-peers closest to the key should lo...
#define GNUNET_free(ptr)
Wrapper around free.