GNUnet  0.11.x
gnunet-service-dht_datacache.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2011, 2015, 2017 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  */
26 #include "platform.h"
27 #include "gnunet_datacache_lib.h"
31 #include "gnunet-service-dht.h"
32 
33 #define LOG(kind, ...) GNUNET_log_from (kind, "dht-dhtcache", __VA_ARGS__)
34 
39 #define NUM_CLOSEST 42
40 
45 
46 
59 void
61  const struct GNUNET_HashCode *key,
62  unsigned int put_path_length,
63  const struct GNUNET_PeerIdentity *put_path,
65  size_t data_size,
66  const void *data)
67 {
68  int r;
69 
70  if (NULL == datacache)
71  {
73  _ ("%s request received, but have no datacache!\n"), "PUT");
74  return;
75  }
76  if (data_size >= GNUNET_MAX_MESSAGE_SIZE)
77  {
78  GNUNET_break (0);
79  return;
80  }
81  /* Put size is actual data size plus struct overhead plus path length (if any) */
83  gettext_noop ("# ITEMS stored in datacache"),
84  1,
85  GNUNET_NO);
86  r = GNUNET_DATACACHE_put (datacache,
87  key,
90  data_size,
91  data,
92  type,
93  expiration,
94  put_path_length,
95  put_path);
97  "DATACACHE PUT for key %s [%u] completed (%d) after %u hops\n",
98  GNUNET_h2s (key),
99  data_size,
100  r,
101  put_path_length);
102 }
103 
104 
109 {
113  const void *xquery;
114 
119 
124 
129 
133  void *gc_cls;
134 
138  size_t xquery_size;
139 
144 };
145 
146 
161 static int
163  const struct GNUNET_HashCode *key,
164  size_t data_size,
165  const char *data,
166  enum GNUNET_BLOCK_Type type,
167  struct GNUNET_TIME_Absolute exp,
168  unsigned int put_path_length,
169  const struct GNUNET_PeerIdentity *put_path)
170 {
171  static char non_null;
172  struct GetRequestContext *ctx = cls;
174 
175  if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
176  {
177  GNUNET_break (0); /* why does datacache return expired values? */
178  return GNUNET_OK; /* skip expired record */
179  }
180  if ((NULL == data) &&
181  (0 == data_size))
182  data = &non_null; /* point anywhere, but not to NULL */
183 
184  eval
186  type,
187  ctx->bg,
189  key,
190  ctx->xquery,
191  ctx->xquery_size,
192  data,
193  data_size);
195  "Found reply for query %s in datacache, evaluation result is %d\n",
196  GNUNET_h2s (key),
197  (int) eval);
198  ctx->eval = eval;
199  switch (eval)
200  {
203  /* forward to local clients */
206  ("# Good RESULTS found in datacache"), 1,
207  GNUNET_NO);
208  ctx->gc (ctx->gc_cls,
209  type,
210  exp,
211  key,
212  put_path_length, put_path,
213  0, NULL,
214  data, data_size);
215  break;
216 
219  gettext_noop (
220  "# Duplicate RESULTS found in datacache"),
221  1,
222  GNUNET_NO);
223  break;
224 
227  gettext_noop (
228  "# Invalid RESULTS found in datacache"),
229  1,
230  GNUNET_NO);
231  break;
232 
235  gettext_noop (
236  "# Irrelevant RESULTS found in datacache"),
237  1,
238  GNUNET_NO);
239  break;
240 
242  GNUNET_break (0);
243  break;
244 
246  GNUNET_break_op (0);
247  return GNUNET_SYSERR;
248 
251  gettext_noop (
252  "# Unsupported RESULTS found in datacache"),
253  1,
254  GNUNET_NO);
256  _ ("Unsupported block type (%u) in local response!\n"),
257  type);
258  break;
259  }
261 }
262 
263 
278  enum GNUNET_BLOCK_Type type,
279  const void *xquery,
280  size_t xquery_size,
281  struct GNUNET_BLOCK_Group *bg,
283  void *gc_cls)
284 {
285  struct GetRequestContext ctx;
286  unsigned int r;
287 
288  if (NULL == datacache)
291  gettext_noop ("# GET requests given to datacache"),
292  1,
293  GNUNET_NO);
295  ctx.key = *key;
296  ctx.xquery = xquery;
297  ctx.xquery_size = xquery_size;
298  ctx.bg = bg;
299  ctx.gc = gc;
300  ctx.gc_cls = gc_cls;
301  r = GNUNET_DATACACHE_get (datacache,
302  key,
303  type,
305  &ctx);
307  "DATACACHE GET for key %s completed (%d). %u results found.\n",
308  GNUNET_h2s (key),
309  ctx.eval,
310  r);
311  return ctx.eval;
312 }
313 
314 
329 static int
331  const struct GNUNET_HashCode *key,
332  size_t data_size,
333  const char *data,
334  enum GNUNET_BLOCK_Type type,
335  struct GNUNET_TIME_Absolute exp,
336  unsigned int path_info_len,
337  const struct GNUNET_PeerIdentity *path_info)
338 {
339  struct GNUNET_HashCode *dest = cls;
340 
341  *dest = *key;
342  return GNUNET_OK; /* should actually not matter which we return */
343 }
344 
345 
354 int
356 {
357  if (0 ==
358  GNUNET_DATACACHE_get_random (datacache,
360  key))
361  {
362  /* randomize key in this case */
364  key);
365  return GNUNET_SYSERR;
366  }
367  return GNUNET_OK;
368 }
369 
370 
375 {
380 
384  void *cb_cls;
385 };
386 
387 
402 static int
404  const struct GNUNET_HashCode *key,
405  size_t size,
406  const char *data,
407  enum GNUNET_BLOCK_Type type,
408  struct GNUNET_TIME_Absolute exp,
409  unsigned int put_path_length,
410  const struct GNUNET_PeerIdentity *put_path)
411 {
412  const struct SuccContext *sc = cls;
413 
414  /* NOTE: The datacache currently does not store the RO from
415  the original 'put', so we don't know the 'correct' option
416  at this point anymore. Thus, we conservatively assume
417  that recording is desired (for now). */
418  sc->cb (sc->cb_cls,
420  key,
421  type,
422  put_path_length, put_path,
423  exp,
424  data,
425  size);
426  return GNUNET_OK;
427 }
428 
429 
438 void
441  void *cb_cls)
442 {
443  struct SuccContext sc;
444 
445  sc.cb = cb;
446  sc.cb_cls = cb_cls;
447  (void) GNUNET_DATACACHE_get_closest (datacache,
448  key,
449  NUM_CLOSEST,
451  &sc);
452 }
453 
454 
458 void
460 {
461  datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache");
462 }
463 
464 
468 void
470 {
471  if (NULL != datacache)
472  {
473  GNUNET_DATACACHE_destroy (datacache);
474  datacache = NULL;
475  }
476 }
477 
478 
479 /* end of gnunet-service-dht_datacache.c */
Block does not match query (invalid result)
#define NUM_CLOSEST
How many "closest" results to we return for migration when asked (at most)?
enum GNUNET_BLOCK_EvaluationResult eval
Return value to give back.
GNUnet DHT globals.
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
We should keep track of the route that the message took in the P2P network.
size_t xquery_size
Number of bytes in xquery.
void GDS_DATACACHE_init()
Initialize datacache subsystem.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
void(* GDS_DATACACHE_GetCallback)(void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a result for a GET operation.
unsigned int GNUNET_CRYPTO_hash_matching_bits(const struct GNUNET_HashCode *first, const struct GNUNET_HashCode *second)
Determine how many low order bits match in two struct GNUNET_HashCodes.
Definition: crypto_hash.c:272
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
void GDS_DATACACHE_done()
Shutdown datacache subsystem.
void GNUNET_DATACACHE_destroy(struct GNUNET_DATACACHE_Handle *h)
Destroy a data cache (and free associated resources).
Definition: datacache.c:212
GDS_DATACACHE_GetCallback gc
Function to call on results.
void(* GDS_DATACACHE_SuccessorCallback)(void *cls, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, struct GNUNET_TIME_Absolute expiration, const void *data, size_t data_size)
Send the get result to requesting client.
Block does not match xquery (valid result, not relevant for the request)
int GNUNET_DATACACHE_put(struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode *key, uint32_t xor_distance, size_t data_size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info)
Store an item in the datastore.
Definition: datacache.c:250
#define GNUNET_NO
Definition: gnunet_common.h:78
static int datacache_get_successors_iterator(void *cls, const struct GNUNET_HashCode *key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path)
Iterator for local get request results,.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
struct GNUNET_HashCode my_identity_hash
Hash of the identity of this peer.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_BLOCK_Context * GDS_block_context
Our handle to the BLOCK library.
struct GNUNET_HashCode key
The key this request was about.
int GDS_DATACACHE_get_random_key(struct GNUNET_HashCode *key)
Obtain a random key from the datacache.
void * cb_cls
Closure for cb.
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:144
#define LOG(kind,...)
Valid result, but suppressed because it is a duplicate.
unsigned int GNUNET_DATACACHE_get(struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Iterate over the results for a particular key in the datacache.
Definition: datacache.c:313
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum GNUNET_BLOCK_EvaluationResult GNUNET_BLOCK_evaluate(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *group, enum GNUNET_BLOCK_EvaluationOptions eo, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size)
Function called to validate a reply or a request.
Definition: block.c:338
void GDS_DATACACHE_handle_put(struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data)
Handle a datum we&#39;ve received from another peer.
struct GNUNET_DATACACHE_Handle * GNUNET_DATACACHE_create(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Create a data cache.
Definition: datacache.c:133
Last possible valid result.
Randomness for IVs etc.
GNUnet DHT tracking of requests for routing replies.
A 512-bit hashcode.
Context containing information about a GET request.
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
struct GNUNET_BLOCK_Group * bg
Block group to use to evaluate replies (updated)
The block is obtained from the local database, skip cryptographic checks.
Valid result, and there may be more.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
GNUNET_BLOCK_EvaluationResult
Possible ways for how a block may relate to a query.
static struct GNUNET_FS_SearchContext * sc
Definition: gnunet-search.c:37
GNUnet DHT routing code.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
GDS_DATACACHE_SuccessorCallback cb
Function to call on the result.
Specified block type not supported by this plugin.
Closure for datacache_get_successors_iterator().
void GDS_DATACACHE_get_successors(const struct GNUNET_HashCode *key, GDS_DATACACHE_SuccessorCallback cb, void *cb_cls)
Handle a request for data close to a key that we have received from another peer. ...
GNUnet DHT service&#39;s datacache integration.
The identity of the host (wraps the signing key of the peer).
Internal state of the datacache library.
Definition: datacache.c:40
Query format does not match block type (invalid query).
static int datacache_get_iterator(void *cls, const struct GNUNET_HashCode *key, size_t data_size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path)
Iterator for local get request results,.
#define GNUNET_log(kind,...)
Block group data.
void * gc_cls
Closure for gc.
enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback gc, void *gc_cls)
Handle a GET request we&#39;ve received from another peer.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Time for absolute times used by GNUnet, in microseconds.
static int datacache_random_iterator(void *cls, const struct GNUNET_HashCode *key, size_t data_size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info)
Function called with a random element from the datacache.
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
Configuration we use.
static struct GNUNET_DATACACHE_Handle * datacache
Handle to the datacache service (for inserting/retrieving data)
uint32_t data
The data value.
unsigned int GNUNET_DATACACHE_get_closest(struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode *key, unsigned int num_results, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Iterate over the results that are "close" to a particular key in the datacache.
Definition: datacache.c:380
Query is valid, no reply given.
unsigned int GNUNET_DATACACHE_get_random(struct GNUNET_DATACACHE_Handle *h, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Obtain a random element from the datacache.
Definition: datacache.c:352
const void * xquery
extended query (see gnunet_block_lib.h).
#define gettext_noop(String)
Definition: gettext.h:69