aboutsummaryrefslogtreecommitdiff
path: root/src/dht/gnunet-service-dht_datacache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dht/gnunet-service-dht_datacache.c')
-rw-r--r--src/dht/gnunet-service-dht_datacache.c479
1 files changed, 0 insertions, 479 deletions
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
deleted file mode 100644
index 7eded2152..000000000
--- a/src/dht/gnunet-service-dht_datacache.c
+++ /dev/null
@@ -1,479 +0,0 @@
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 */
20/**
21 * @file dht/gnunet-service-dht_datacache.c
22 * @brief GNUnet DHT service's datacache integration
23 * @author Christian Grothoff
24 * @author Nathan Evans
25 */
26#include "platform.h"
27#include "gnunet_datacache_lib.h"
28#include "gnunet-service-dht_datacache.h"
29#include "gnunet-service-dht_neighbours.h"
30#include "gnunet-service-dht_routing.h"
31#include "gnunet-service-dht.h"
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "dht-dhtcache", __VA_ARGS__)
34
35/**
36 * How many "closest" results to we return for migration when
37 * asked (at most)?
38 */
39#define NUM_CLOSEST 42
40
41/**
42 * Handle to the datacache service (for inserting/retrieving data)
43 */
44static struct GNUNET_DATACACHE_Handle *datacache;
45
46
47/**
48 * Handle a datum we've received from another peer. Cache if
49 * possible.
50 *
51 * @param expiration when will the reply expire
52 * @param key the query this reply is for
53 * @param put_path_length number of peers in @a put_path
54 * @param put_path path the reply took on put
55 * @param type type of the reply
56 * @param data_size number of bytes in @a data
57 * @param data application payload data
58 */
59void
60GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
61 const struct GNUNET_HashCode *key,
62 unsigned int put_path_length,
63 const struct GNUNET_PeerIdentity *put_path,
64 enum GNUNET_BLOCK_Type type,
65 size_t data_size,
66 const void *data)
67{
68 int r;
69
70 if (NULL == datacache)
71 {
72 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
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) */
82 GNUNET_STATISTICS_update (GDS_stats,
83 gettext_noop ("# ITEMS stored in datacache"),
84 1,
85 GNUNET_NO);
86 r = GNUNET_DATACACHE_put (datacache,
87 key,
88 GNUNET_CRYPTO_hash_matching_bits (key,
89 &my_identity_hash),
90 data_size,
91 data,
92 type,
93 expiration,
94 put_path_length,
95 put_path);
96 LOG (GNUNET_ERROR_TYPE_DEBUG,
97 "DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n",
98 GNUNET_h2s (key),
99 (unsigned long) data_size,
100 r,
101 put_path_length);
102}
103
104
105/**
106 * Context containing information about a GET request.
107 */
108struct GetRequestContext
109{
110 /**
111 * extended query (see gnunet_block_lib.h).
112 */
113 const void *xquery;
114
115 /**
116 * The key this request was about
117 */
118 struct GNUNET_HashCode key;
119
120 /**
121 * Block group to use to evaluate replies (updated)
122 */
123 struct GNUNET_BLOCK_Group *bg;
124
125 /**
126 * Function to call on results.
127 */
128 GDS_DATACACHE_GetCallback gc;
129
130 /**
131 * Closure for @e gc.
132 */
133 void *gc_cls;
134
135 /**
136 * Number of bytes in xquery.
137 */
138 size_t xquery_size;
139
140 /**
141 * Return value to give back.
142 */
143 enum GNUNET_BLOCK_EvaluationResult eval;
144};
145
146
147/**
148 * Iterator for local get request results,
149 *
150 * @param cls closure for iterator, a `struct GetRequestContext`
151 * @param exp when does this value expire?
152 * @param key the key this data is stored under
153 * @param data_size the size of the data identified by key
154 * @param data the actual data
155 * @param type the type of the @a data
156 * @param put_path_length number of peers in @a put_path
157 * @param put_path path the reply took on put
158 * @return #GNUNET_OK to continue iteration, anything else
159 * to stop iteration.
160 */
161static int
162datacache_get_iterator (void *cls,
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;
173 enum GNUNET_BLOCK_EvaluationResult eval;
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
185 = GNUNET_BLOCK_evaluate (GDS_block_context,
186 type,
187 ctx->bg,
188 GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO,
189 key,
190 ctx->xquery,
191 ctx->xquery_size,
192 data,
193 data_size);
194 LOG (GNUNET_ERROR_TYPE_DEBUG,
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 {
201 case GNUNET_BLOCK_EVALUATION_OK_MORE:
202 case GNUNET_BLOCK_EVALUATION_OK_LAST:
203 /* forward to local clients */
204 GNUNET_STATISTICS_update (GDS_stats,
205 gettext_noop
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
217 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
218 GNUNET_STATISTICS_update (GDS_stats,
219 gettext_noop (
220 "# Duplicate RESULTS found in datacache"),
221 1,
222 GNUNET_NO);
223 break;
224
225 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
226 GNUNET_STATISTICS_update (GDS_stats,
227 gettext_noop (
228 "# Invalid RESULTS found in datacache"),
229 1,
230 GNUNET_NO);
231 break;
232
233 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
234 GNUNET_STATISTICS_update (GDS_stats,
235 gettext_noop (
236 "# Irrelevant RESULTS found in datacache"),
237 1,
238 GNUNET_NO);
239 break;
240
241 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
242 GNUNET_break (0);
243 break;
244
245 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
246 GNUNET_break_op (0);
247 return GNUNET_SYSERR;
248
249 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
250 GNUNET_STATISTICS_update (GDS_stats,
251 gettext_noop (
252 "# Unsupported RESULTS found in datacache"),
253 1,
254 GNUNET_NO);
255 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
256 _ ("Unsupported block type (%u) in local response!\n"),
257 type);
258 break;
259 }
260 return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK;
261}
262
263
264/**
265 * Handle a GET request we've received from another peer.
266 *
267 * @param key the query
268 * @param type requested data type
269 * @param xquery extended query
270 * @param xquery_size number of bytes in @a xquery
271 * @param bg block group to use for reply evaluation
272 * @param gc function to call on the results
273 * @param gc_cls closure for @a gc
274 * @return evaluation result for the local replies
275 */
276enum GNUNET_BLOCK_EvaluationResult
277GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
278 enum GNUNET_BLOCK_Type type,
279 const void *xquery,
280 size_t xquery_size,
281 struct GNUNET_BLOCK_Group *bg,
282 GDS_DATACACHE_GetCallback gc,
283 void *gc_cls)
284{
285 struct GetRequestContext ctx;
286 unsigned int r;
287
288 if (NULL == datacache)
289 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
290 GNUNET_STATISTICS_update (GDS_stats,
291 gettext_noop ("# GET requests given to datacache"),
292 1,
293 GNUNET_NO);
294 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
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,
304 &datacache_get_iterator,
305 &ctx);
306 LOG (GNUNET_ERROR_TYPE_DEBUG,
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
315/**
316 * Function called with a random element from the datacache.
317 * Stores the key in the closure.
318 *
319 * @param cls a `struct GNUNET_HashCode *`, where to store the @a key
320 * @param key key for the content
321 * @param data_size number of bytes in @a data
322 * @param data content stored
323 * @param type type of the content
324 * @param exp when will the content expire?
325 * @param path_info_len number of entries in @a path_info
326 * @param path_info a path through the network
327 * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
328 */
329static int
330datacache_random_iterator (void *cls,
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
346/**
347 * Obtain a random key from the datacache.
348 * Used by Whanau for load-balancing.
349 *
350 * @param[out] key where to store the key of a random element,
351 * randomized by PRNG if datacache is empty
352 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
353 */
354int
355GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key)
356{
357 if (0 ==
358 GNUNET_DATACACHE_get_random (datacache,
359 &datacache_random_iterator,
360 key))
361 {
362 /* randomize key in this case */
363 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
364 key);
365 return GNUNET_SYSERR;
366 }
367 return GNUNET_OK;
368}
369
370
371/**
372 * Closure for #datacache_get_successors_iterator().
373 */
374struct SuccContext
375{
376 /**
377 * Function to call on the result
378 */
379 GDS_DATACACHE_SuccessorCallback cb;
380
381 /**
382 * Closure for @e cb.
383 */
384 void *cb_cls;
385};
386
387
388/**
389 * Iterator for local get request results,
390 *
391 * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
392 * @param key the key this data is stored under
393 * @param size the size of the data identified by key
394 * @param data the actual data
395 * @param type the type of the data
396 * @param exp when does this value expire?
397 * @param put_path_length number of peers in @a put_path
398 * @param put_path path the reply took on put
399 * @return #GNUNET_OK to continue iteration, anything else
400 * to stop iteration.
401 */
402static int
403datacache_get_successors_iterator (void *cls,
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,
419 GNUNET_DHT_RO_RECORD_ROUTE,
420 key,
421 type,
422 put_path_length, put_path,
423 exp,
424 data,
425 size);
426 return GNUNET_OK;
427}
428
429
430/**
431 * Handle a request for data close to a key that we have received from
432 * another peer.
433 *
434 * @param key the location at which the peer is looking for data that is close
435 * @param cb function to call with the result
436 * @param cb_cls closure for @a cb
437 */
438void
439GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key,
440 GDS_DATACACHE_SuccessorCallback cb,
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,
450 &datacache_get_successors_iterator,
451 &sc);
452}
453
454
455/**
456 * Initialize datacache subsystem.
457 */
458void
459GDS_DATACACHE_init ()
460{
461 datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache");
462}
463
464
465/**
466 * Shutdown datacache subsystem.
467 */
468void
469GDS_DATACACHE_done ()
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 */