GNUnet  0.11.x
plugin_peerstore_flat.c
Go to the documentation of this file.
1 /*
2  * This file is part of GNUnet
3  * Copyright (C) 2015 Christian Grothoff (and other contributing authors)
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 
27 #include "platform.h"
30 #include "peerstore.h"
31 
35 struct Plugin
36 {
40  const struct GNUNET_CONFIGURATION_Handle *cfg;
41 
46 
51 
55  void *iter_cls;
56 
60  const char *iter_key;
61 
66 
70  const char *iter_sub_system;
71 
76 
80  uint64_t deleted_entries;
81 
85  uint64_t exp_changes;
86 
90  char *fn;
91 
96 };
97 
98 
99 static int
100 delete_entries (void *cls,
101  const struct GNUNET_HashCode *key,
102  void *value)
103 {
104  struct Plugin *plugin = cls;
105  struct GNUNET_PEERSTORE_Record *entry = value;
106 
107  if (0 != strcmp (plugin->iter_key, entry->key))
108  return GNUNET_YES;
109  if (0 != memcmp (plugin->iter_peer,
110  &entry->peer,
111  sizeof(struct GNUNET_PeerIdentity)))
112  return GNUNET_YES;
113  if (0 != strcmp (plugin->iter_sub_system, entry->sub_system))
114  return GNUNET_YES;
115 
116  GNUNET_CONTAINER_multihashmap_remove (plugin->hm, key, value);
117  plugin->deleted_entries++;
118  return GNUNET_YES;
119 }
120 
121 
131 static int
133  const struct GNUNET_PeerIdentity *peer,
134  const char *key)
135 {
136  struct Plugin *plugin = cls;
137 
138  plugin->iter_sub_system = sub_system;
139  plugin->iter_peer = peer;
140  plugin->iter_key = key;
141  plugin->deleted_entries = 0;
142 
145  plugin);
146  return plugin->deleted_entries;
147 }
148 
149 
150 static int
151 expire_entries (void *cls,
152  const struct GNUNET_HashCode *key,
153  void *value)
154 {
155  struct Plugin *plugin = cls;
156  struct GNUNET_PEERSTORE_Record *entry = value;
157 
158  if (entry->expiry.abs_value_us < plugin->iter_now.abs_value_us)
159  {
160  GNUNET_CONTAINER_multihashmap_remove (plugin->hm, key, value);
161  plugin->exp_changes++;
162  }
163  return GNUNET_YES;
164 }
165 
166 
177 static int
180  void *cont_cls)
181 {
182  struct Plugin *plugin = cls;
183 
184  plugin->exp_changes = 0;
185  plugin->iter_now = now;
186 
189  plugin);
190  if (NULL != cont)
191  {
192  cont (cont_cls, plugin->exp_changes);
193  }
194  return GNUNET_OK;
195 }
196 
197 
198 static int
199 iterate_entries (void *cls,
200  const struct GNUNET_HashCode *key,
201  void *value)
202 {
203  struct Plugin *plugin = cls;
204  struct GNUNET_PEERSTORE_Record *entry = value;
205 
206  if ((NULL != plugin->iter_peer) &&
207  (0 != memcmp (plugin->iter_peer,
208  &entry->peer,
209  sizeof(struct GNUNET_PeerIdentity))))
210  {
211  return GNUNET_YES;
212  }
213  if ((NULL != plugin->iter_key) &&
214  (0 != strcmp (plugin->iter_key,
215  entry->key)))
216  {
217  return GNUNET_YES;
218  }
219  if (NULL != plugin->iter)
220  plugin->iter (plugin->iter_cls, entry, NULL);
221  plugin->iter_result_found = GNUNET_YES;
222  return GNUNET_YES;
223 }
224 
225 
240 static int
242  const struct GNUNET_PeerIdentity *peer,
243  const char *key,
245  void *iter_cls)
246 {
247  struct Plugin *plugin = cls;
248 
249  plugin->iter = iter;
250  plugin->iter_cls = iter_cls;
251  plugin->iter_peer = peer;
252  plugin->iter_sub_system = sub_system;
253  plugin->iter_key = key;
254 
257  plugin);
258  if (NULL != iter)
259  iter (iter_cls, NULL, NULL);
260  return GNUNET_OK;
261 }
262 
263 
281 static int
282 peerstore_flat_store_record (void *cls, const char *sub_system,
283  const struct GNUNET_PeerIdentity *peer,
284  const char *key, const void *value, size_t size,
285  struct GNUNET_TIME_Absolute expiry,
288  void *cont_cls)
289 {
290  struct Plugin *plugin = cls;
291  struct GNUNET_HashCode hkey;
292  struct GNUNET_PEERSTORE_Record *entry;
293  const char *peer_id;
294 
295 
296  entry = GNUNET_new (struct GNUNET_PEERSTORE_Record);
297  entry->sub_system = GNUNET_strdup (sub_system);
298  entry->key = GNUNET_strdup (key);
299  entry->value = GNUNET_malloc (size);
300  GNUNET_memcpy (entry->value, value, size);
301  entry->value_size = size;
302  entry->peer = *peer;
303  entry->expiry = expiry;
304 
305  peer_id = GNUNET_i2s (peer);
306  GNUNET_CRYPTO_hash (peer_id,
307  strlen (peer_id),
308  &hkey);
309 
311  {
312  peerstore_flat_delete_records (cls, sub_system, peer, key);
313  }
314 
316  &hkey,
317  entry,
319  if (NULL != cont)
320  {
321  cont (cont_cls, GNUNET_OK);
322  }
323  return GNUNET_OK;
324 }
325 
326 
335 static int
337 {
338  char *afsdir;
339  char *key;
340  char *sub_system;
341  const char *peer_id;
342  char *peer;
343  char *value;
344  char *expiry;
345  struct GNUNET_DISK_FileHandle *fh;
346  struct GNUNET_PEERSTORE_Record *entry;
347  struct GNUNET_HashCode hkey;
348  size_t size;
349  char *buffer;
350  char *line;
351 
352  if (GNUNET_OK !=
353  GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "peerstore-flat",
354  "FILENAME", &afsdir))
355  {
357  "FILENAME");
358  return GNUNET_SYSERR;
359  }
360  if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
361  {
363  {
364  GNUNET_break (0);
365  GNUNET_free (afsdir);
366  return GNUNET_SYSERR;
367  }
368  }
369  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
370  plugin->fn = afsdir;
371 
372  fh = GNUNET_DISK_file_open (afsdir,
377  if (NULL == fh)
378  {
380  _ ("Unable to initialize file: %s.\n"),
381  afsdir);
382  return GNUNET_SYSERR;
383  }
384 
385  /* Load data from file into hashmap */
387  GNUNET_NO);
388 
389  if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir,
390  &size,
391  GNUNET_YES,
392  GNUNET_YES))
393  {
395  _ ("Unable to get filesize: %s.\n"),
396  afsdir);
397  return GNUNET_SYSERR;
398  }
399 
400  buffer = GNUNET_malloc (size + 1);
401 
403  buffer,
404  size))
405  {
407  _ ("Unable to read file: %s.\n"),
408  afsdir);
410  GNUNET_free (buffer);
411  return GNUNET_SYSERR;
412  }
413 
414  buffer[size] = '\0';
416  if (0 < size)
417  {
418  line = strtok (buffer, "\n");
419  while (line != NULL)
420  {
421  sub_system = strtok (line, ",");
422  if (NULL == sub_system)
423  break;
424  peer = strtok (NULL, ",");
425  if (NULL == peer)
426  break;
427  key = strtok (NULL, ",");
428  if (NULL == key)
429  break;
430  value = strtok (NULL, ",");
431  if (NULL == value)
432  break;
433  expiry = strtok (NULL, ",");
434  if (NULL == expiry)
435  break;
436  entry = GNUNET_new (struct GNUNET_PEERSTORE_Record);
437  entry->sub_system = GNUNET_strdup (sub_system);
438  entry->key = GNUNET_strdup (key);
439  {
440  size_t s;
441  char *o;
442 
443  o = NULL;
445  strlen (peer),
446  (void**) &o);
447  if (sizeof(struct GNUNET_PeerIdentity) == s)
448  GNUNET_memcpy (&entry->peer,
449  o,
450  s);
451  else
452  GNUNET_break (0);
454  }
456  strlen (value),
457  (void**) &entry->value);
458  if (GNUNET_SYSERR ==
460  &entry->expiry))
461  {
462  GNUNET_free (entry->sub_system);
463  GNUNET_free (entry->key);
464  GNUNET_free (entry);
465  break;
466  }
467  peer_id = GNUNET_i2s (&entry->peer);
468  GNUNET_CRYPTO_hash (peer_id,
469  strlen (peer_id),
470  &hkey);
471 
473  &hkey,
474  entry,
476  }
477  }
478  GNUNET_free (buffer);
479  return GNUNET_OK;
480 }
481 
482 
483 static int
485  const struct GNUNET_HashCode *key,
486  void *value)
487 {
488  struct GNUNET_DISK_FileHandle *fh = cls;
489  struct GNUNET_PEERSTORE_Record *entry = value;
490  char *line;
491  char *peer;
492  const char *expiry;
493  char *val;
494 
496  entry->value_size,
497  &val);
499  GNUNET_STRINGS_base64_encode ((char*) &entry->peer,
500  sizeof(struct GNUNET_PeerIdentity),
501  &peer);
502  GNUNET_asprintf (&line,
503  "%s,%s,%s,%s,%s",
504  entry->sub_system,
505  peer,
506  entry->key,
507  val,
508  expiry);
509  GNUNET_free (val);
510  GNUNET_free (peer);
512  line,
513  strlen (line));
514  GNUNET_free (entry->sub_system);
515  GNUNET_free (entry->key);
516  GNUNET_free (entry->value);
517  GNUNET_free (entry);
518  GNUNET_free (line);
519  return GNUNET_YES;
520 }
521 
522 
528 static void
530 {
531  struct GNUNET_DISK_FileHandle *fh;
532 
533  fh = GNUNET_DISK_file_open (plugin->fn,
539  if (NULL == fh)
540  {
542  _ ("Unable to initialize file: %s.\n"),
543  plugin->fn);
544  return;
545  }
548  fh);
551 }
552 
553 
560 void *
562 {
563  static struct Plugin plugin;
564  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
566 
567  if (NULL != plugin.cfg)
568  return NULL; /* can only initialize once! */
569  memset (&plugin, 0, sizeof(struct Plugin));
570  plugin.cfg = cfg;
571  if (GNUNET_OK != database_setup (&plugin))
572  {
573  database_shutdown (&plugin);
574  return NULL;
575  }
577  api->cls = &plugin;
581  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Flat plugin is running\n");
582  return api;
583 }
584 
585 
592 void *
594 {
596  struct Plugin *plugin = api->cls;
597 
598  database_shutdown (plugin);
599  plugin->cfg = NULL;
600  GNUNET_free (api);
601  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Flat plugin is finished\n");
602  return NULL;
603 }
604 
605 
606 /* end of plugin_peerstore_sqlite.c */
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:544
Create file if it doesn&#39;t exist.
void(* GNUNET_PEERSTORE_Processor)(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1345
struct GNUNET_PeerIdentity peer
Peer Identity.
void * libgnunet_plugin_peerstore_flat_done(void *cls)
Exit point from the plugin.
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:732
Delete any previous values for the given key before storing the given value.
size_t value_size
Size of value BLOB.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_TIME_Absolute iter_now
Iterator time.
uint32_t options
Options for addresses.
char * key
TLS key.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
int GNUNET_STRINGS_fancy_time_to_absolute(const char *fancy_time, struct GNUNET_TIME_Absolute *atime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:402
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int(* store_record)(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a record in the peerstore.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
uint64_t abs_value_us
The actual value.
void * cls
Closure to pass to all plugin functions.
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
IPC messages.
static int iterate_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
char * key
Record key string.
int(* expire_records)(void *cls, struct GNUNET_TIME_Absolute now, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Delete expired records (expiry < now)
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
uint64_t deleted_entries
Deleted entries.
void * value
Record value BLOB.
static char * line
Desired phone line (string to be converted to a hash).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
static int store_and_free_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
static int peerstore_flat_expire_records(void *cls, struct GNUNET_TIME_Absolute now, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Delete expired records (expiry < now)
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
Truncate file if it exists.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:820
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static int delete_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
const struct GNUNET_PeerIdentity * iter_peer
Iterator peer.
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
GNUNET_PEERSTORE_StoreOption
Options for storing values in PEERSTORE.
static int fh
Handle to the unique file.
void * libgnunet_plugin_peerstore_flat_init(void *cls)
Entry point for the plugin.
static int expire_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
struct returned by the initialization function of the plugin
A 512-bit hashcode.
static int peerstore_flat_delete_records(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key)
Delete records with the given key.
static char * plugin
Solver plugin name as string.
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1920
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1855
static int peerstore_flat_store_record(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a record in the peerstore.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
void(* GNUNET_PEERSTORE_Continuation)(void *cls, int success)
Continuation called with a status result.
struct GNUNET_CONTAINER_MultiHashMap * hm
HashMap.
void * iter_cls
Iterator cls.
int(* iterate_records)(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor iter, void *iter_cls)
Iterate over the records given an optional peer id and/or key.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:257
char * fn
Filename used for the DB.
Allow multiple values with the same key.
uint64_t exp_changes
Expired entries.
The identity of the host (wraps the signing key of the peer).
unsigned long long size
Size of all values we&#39;re storing.
configuration data
Definition: configuration.c:85
struct GNUNET_TIME_Absolute expiry
Expiry time of entry.
char * sub_system
Responsible sub system string.
Handle for a plugin.
Definition: block.c:37
Single PEERSTORE record.
#define GNUNET_log(kind,...)
static int peerstore_flat_iterate_records(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor iter, void *iter_cls)
Iterate over the records given an optional peer id and/or key.
Open the file for both reading and writing.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
static int database_setup(struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
const char * iter_sub_system
Iterator subsystem.
int iter_result_found
Result found bool.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
const char * iter_key
iterator key
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1268
GNUNET_PEERSTORE_Processor iter
Iterator.
Handle used to access files (and pipes).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.