aboutsummaryrefslogtreecommitdiff
path: root/src/namecache/namecache_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namecache/namecache_api.c')
-rw-r--r--src/namecache/namecache_api.c567
1 files changed, 0 insertions, 567 deletions
diff --git a/src/namecache/namecache_api.c b/src/namecache/namecache_api.c
deleted file mode 100644
index 70c848037..000000000
--- a/src/namecache/namecache_api.c
+++ /dev/null
@@ -1,567 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2016 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 namecache/namecache_api.c
23 * @brief API to access the NAMECACHE service
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_constants.h"
33#include "gnunet_dnsparser_lib.h"
34#include "gnunet_gnsrecord_lib.h"
35#include "gnunet_signatures.h"
36#include "gnunet_namecache_service.h"
37#include "namecache.h"
38
39
40#define LOG(kind, ...) GNUNET_log_from (kind, "namecache-api", __VA_ARGS__)
41
42
43/**
44 * An QueueEntry used to store information for a pending
45 * NAMECACHE record operation
46 */
47struct GNUNET_NAMECACHE_QueueEntry
48{
49 /**
50 * Kept in a DLL.
51 */
52 struct GNUNET_NAMECACHE_QueueEntry *next;
53
54 /**
55 * Kept in a DLL.
56 */
57 struct GNUNET_NAMECACHE_QueueEntry *prev;
58
59 /**
60 * Main handle to access the namecache.
61 */
62 struct GNUNET_NAMECACHE_Handle *nsh;
63
64 /**
65 * Continuation to call
66 */
67 GNUNET_NAMECACHE_ContinuationWithStatus cont;
68
69 /**
70 * Closure for @e cont.
71 */
72 void *cont_cls;
73
74 /**
75 * Function to call with the blocks we get back; or NULL.
76 */
77 GNUNET_NAMECACHE_BlockProcessor block_proc;
78
79 /**
80 * Closure for @e block_proc.
81 */
82 void *block_proc_cls;
83
84 /**
85 * The operation id this zone iteration operation has
86 */
87 uint32_t op_id;
88};
89
90
91/**
92 * Connection to the NAMECACHE service.
93 */
94struct GNUNET_NAMECACHE_Handle
95{
96 /**
97 * Configuration to use.
98 */
99 const struct GNUNET_CONFIGURATION_Handle *cfg;
100
101 /**
102 * Message queue to service.
103 */
104 struct GNUNET_MQ_Handle *mq;
105
106 /**
107 * Currently pending transmission request (or NULL).
108 */
109 struct GNUNET_CLIENT_TransmitHandle *th;
110
111 /**
112 * Head of pending namecache queue entries
113 */
114 struct GNUNET_NAMECACHE_QueueEntry *op_head;
115
116 /**
117 * Tail of pending namecache queue entries
118 */
119 struct GNUNET_NAMECACHE_QueueEntry *op_tail;
120
121 /**
122 * Reconnect task
123 */
124 struct GNUNET_SCHEDULER_Task *reconnect_task;
125
126 /**
127 * Delay introduced before we reconnect.
128 */
129 struct GNUNET_TIME_Relative reconnect_delay;
130
131 /**
132 * Should we reconnect to service due to some serious error?
133 */
134 int reconnect;
135
136 /**
137 * The last operation id used for a NAMECACHE operation
138 */
139 uint32_t last_op_id_used;
140};
141
142
143/**
144 * Disconnect from service and then reconnect.
145 *
146 * @param h our handle
147 */
148static void
149force_reconnect (struct GNUNET_NAMECACHE_Handle *h);
150
151
152/**
153 * Find queue entry for the given @a rid.
154 *
155 * @param h handle to search
156 * @param rid request ID to look for
157 * @return NULL if not found, otherwise the queue entry (removed from the queue)
158 */
159static struct GNUNET_NAMECACHE_QueueEntry *
160find_qe (struct GNUNET_NAMECACHE_Handle *h,
161 uint32_t rid)
162{
163 struct GNUNET_NAMECACHE_QueueEntry *qe;
164
165 for (qe = h->op_head; qe != NULL; qe = qe->next)
166 {
167 if (qe->op_id == rid)
168 {
169 GNUNET_CONTAINER_DLL_remove (h->op_head,
170 h->op_tail,
171 qe);
172 return qe;
173 }
174 }
175 return NULL;
176}
177
178
179/**
180 * Handle an incoming message of type
181 * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
182 *
183 * @param cls the `struct GNUNET_NAMECACHE_Handle`
184 * @param msg the message we received
185 */
186static int
187check_lookup_block_response (void *cls,
188 const struct LookupBlockResponseMessage *msg)
189{
190 /* any length will do, format validation is in handler */
191 return GNUNET_OK;
192}
193
194
195/**
196 * Handle an incoming message of type
197 * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
198 *
199 * @param cls the `struct GNUNET_NAMECACHE_Handle`
200 * @param msg the message we received
201 */
202static void
203handle_lookup_block_response (void *cls,
204 const struct LookupBlockResponseMessage *msg)
205{
206 struct GNUNET_NAMECACHE_Handle *h = cls;
207 size_t size;
208 struct GNUNET_NAMECACHE_QueueEntry *qe;
209
210 LOG (GNUNET_ERROR_TYPE_DEBUG,
211 "Received LOOKUP_BLOCK_RESPONSE\n");
212 qe = find_qe (h,
213 ntohl (msg->gns_header.r_id));
214 if (NULL == qe)
215 return;
216 if (0 == GNUNET_TIME_absolute_ntoh (msg->expire).abs_value_us)
217 {
218 /* no match found */
219 if (NULL != qe->block_proc)
220 qe->block_proc (qe->block_proc_cls,
221 NULL);
222 GNUNET_free (qe);
223 return;
224 }
225 size = ntohs (msg->gns_header.header.size)
226 - sizeof(struct LookupBlockResponseMessage);
227 {
228 char buf[size] GNUNET_ALIGN;
229 struct GNUNET_GNSRECORD_Block *block;
230
231 memset (buf, 0, size);
232 block = (struct GNUNET_GNSRECORD_Block *) buf;
233 GNUNET_memcpy (block,
234 &msg[1],
235 size);
236 if (GNUNET_OK !=
237 GNUNET_GNSRECORD_block_verify (block))
238 {
239 GNUNET_break (0);
240 if (NULL != qe->block_proc)
241 qe->block_proc (qe->block_proc_cls,
242 NULL);
243 force_reconnect (h);
244 }
245 else
246 {
247 if (NULL != qe->block_proc)
248 qe->block_proc (qe->block_proc_cls,
249 block);
250 }
251 }
252 GNUNET_free (qe);
253}
254
255
256/**
257 * Handle an incoming message of type
258 * #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE
259 *
260 * @param cls the `struct GNUNET_NAMECACHE_Handle`
261 * @param msg the message we received
262 * @param size the message size
263 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client
264 */
265static void
266handle_block_cache_response (void *cls,
267 const struct BlockCacheResponseMessage *msg)
268{
269 struct GNUNET_NAMECACHE_Handle *h = cls;
270 struct GNUNET_NAMECACHE_QueueEntry *qe;
271 int res;
272
273 LOG (GNUNET_ERROR_TYPE_DEBUG,
274 "Received BLOCK_CACHE_RESPONSE\n");
275 qe = find_qe (h,
276 ntohl (msg->gns_header.r_id));
277 if (NULL == qe)
278 return;
279 res = ntohl (msg->op_result);
280 /* TODO: add actual error message from namecache to response... */
281 if (NULL != qe->cont)
282 qe->cont (qe->cont_cls,
283 res,
284 (GNUNET_OK == res)
285 ? NULL
286 : _ ("Namecache failed to cache block"));
287 GNUNET_free (qe);
288}
289
290
291/**
292 * Generic error handler, called with the appropriate error code and
293 * the same closure specified at the creation of the message queue.
294 * Not every message queue implementation supports an error handler.
295 *
296 * @param cls closure with the `struct GNUNET_NAMECACHE_Handle *`
297 * @param error error code
298 */
299static void
300mq_error_handler (void *cls,
301 enum GNUNET_MQ_Error error)
302{
303 struct GNUNET_NAMECACHE_Handle *h = cls;
304
305 force_reconnect (h);
306}
307
308
309/**
310 * Reconnect to namecache service.
311 *
312 * @param h the handle to the NAMECACHE service
313 */
314static void
315reconnect (struct GNUNET_NAMECACHE_Handle *h)
316{
317 struct GNUNET_MQ_MessageHandler handlers[] = {
318 GNUNET_MQ_hd_var_size (lookup_block_response,
319 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE,
320 struct LookupBlockResponseMessage,
321 h),
322 GNUNET_MQ_hd_fixed_size (block_cache_response,
323 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE,
324 struct BlockCacheResponseMessage,
325 h),
326 GNUNET_MQ_handler_end ()
327 };
328
329 GNUNET_assert (NULL == h->mq);
330 h->mq = GNUNET_CLIENT_connect (h->cfg,
331 "namecache",
332 handlers,
333 &mq_error_handler,
334 h);
335}
336
337
338/**
339 * Re-establish the connection to the service.
340 *
341 * @param cls handle to use to re-connect.
342 */
343static void
344reconnect_task (void *cls)
345{
346 struct GNUNET_NAMECACHE_Handle *h = cls;
347
348 h->reconnect_task = NULL;
349 reconnect (h);
350}
351
352
353/**
354 * Disconnect from service and then reconnect.
355 *
356 * @param h our handle
357 */
358static void
359force_reconnect (struct GNUNET_NAMECACHE_Handle *h)
360{
361 struct GNUNET_NAMECACHE_QueueEntry *qe;
362
363 h->reconnect = GNUNET_NO;
364 GNUNET_MQ_destroy (h->mq);
365 h->mq = NULL;
366 while (NULL != (qe = h->op_head))
367 {
368 GNUNET_CONTAINER_DLL_remove (h->op_head,
369 h->op_tail,
370 qe);
371 if (NULL != qe->cont)
372 qe->cont (qe->cont_cls,
373 GNUNET_SYSERR,
374 _ ("Error communicating with namecache service"));
375 GNUNET_free (qe);
376 }
377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
378 "Reconnecting to namecache\n");
379 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
380 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
381 &reconnect_task,
382 h);
383}
384
385
386/**
387 * Get a fresh operation id to distinguish between namecache requests
388 *
389 * @param h the namecache handle
390 * @return next operation id to use
391 */
392static uint32_t
393get_op_id (struct GNUNET_NAMECACHE_Handle *h)
394{
395 return h->last_op_id_used++;
396}
397
398
399/**
400 * Initialize the connection with the NAMECACHE service.
401 *
402 * @param cfg configuration to use
403 * @return handle to the GNS service, or NULL on error
404 */
405struct GNUNET_NAMECACHE_Handle *
406GNUNET_NAMECACHE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
407{
408 struct GNUNET_NAMECACHE_Handle *h;
409
410 h = GNUNET_new (struct GNUNET_NAMECACHE_Handle);
411 h->cfg = cfg;
412 reconnect (h);
413 if (NULL == h->mq)
414 {
415 GNUNET_free (h);
416 return NULL;
417 }
418 return h;
419}
420
421
422/**
423 * Disconnect from the namecache service (and free associated
424 * resources).
425 *
426 * @param h handle to the namecache
427 */
428void
429GNUNET_NAMECACHE_disconnect (struct GNUNET_NAMECACHE_Handle *h)
430{
431 struct GNUNET_NAMECACHE_QueueEntry *q;
432
433 GNUNET_break (NULL == h->op_head);
434 while (NULL != (q = h->op_head))
435 {
436 GNUNET_CONTAINER_DLL_remove (h->op_head,
437 h->op_tail,
438 q);
439 GNUNET_free (q);
440 }
441 if (NULL != h->mq)
442 {
443 GNUNET_MQ_destroy (h->mq);
444 h->mq = NULL;
445 }
446 if (NULL != h->reconnect_task)
447 {
448 GNUNET_SCHEDULER_cancel (h->reconnect_task);
449 h->reconnect_task = NULL;
450 }
451 GNUNET_free (h);
452}
453
454
455/**
456 * Store an item in the namecache. If the item is already present,
457 * it is replaced with the new record.
458 *
459 * @param h handle to the namecache
460 * @param block block to store
461 * @param cont continuation to call when done
462 * @param cont_cls closure for @a cont
463 * @return handle to abort the request, NULL on error
464 */
465struct GNUNET_NAMECACHE_QueueEntry *
466GNUNET_NAMECACHE_block_cache (struct GNUNET_NAMECACHE_Handle *h,
467 const struct GNUNET_GNSRECORD_Block *block,
468 GNUNET_NAMECACHE_ContinuationWithStatus cont,
469 void *cont_cls)
470{
471 struct GNUNET_NAMECACHE_QueueEntry *qe;
472 struct BlockCacheMessage *msg;
473 struct GNUNET_MQ_Envelope *env;
474 uint32_t rid;
475 size_t blen;
476
477 if (NULL == h->mq)
478 return NULL;
479 blen = GNUNET_GNSRECORD_block_get_size (block);
480 rid = get_op_id (h);
481 qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry);
482 qe->nsh = h;
483 qe->cont = cont;
484 qe->cont_cls = cont_cls;
485 qe->op_id = rid;
486 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
487 h->op_tail,
488 qe);
489 /* send msg */
490 env = GNUNET_MQ_msg_extra (msg,
491 blen,
492 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE);
493 msg->gns_header.r_id = htonl (rid);
494 GNUNET_memcpy (&msg[1],
495 block,
496 blen);
497 GNUNET_MQ_send (h->mq,
498 env);
499 return qe;
500}
501
502
503/**
504 * Get a result for a particular key from the namecache. The processor
505 * will only be called once.
506 *
507 * @param h handle to the namecache
508 * @param derived_hash hash of zone key combined with name to lookup
509 * @param proc function to call on the matching block, or with
510 * NULL if there is no matching block
511 * @param proc_cls closure for @a proc
512 * @return a handle that can be used to cancel, NULL on error
513 */
514struct GNUNET_NAMECACHE_QueueEntry *
515GNUNET_NAMECACHE_lookup_block (struct GNUNET_NAMECACHE_Handle *h,
516 const struct GNUNET_HashCode *derived_hash,
517 GNUNET_NAMECACHE_BlockProcessor proc,
518 void *proc_cls)
519{
520 struct GNUNET_NAMECACHE_QueueEntry *qe;
521 struct LookupBlockMessage *msg;
522 struct GNUNET_MQ_Envelope *env;
523 uint32_t rid;
524
525 if (NULL == h->mq)
526 return NULL;
527 LOG (GNUNET_ERROR_TYPE_DEBUG,
528 "Looking for block under %s\n",
529 GNUNET_h2s (derived_hash));
530 rid = get_op_id (h);
531 qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry);
532 qe->nsh = h;
533 qe->block_proc = proc;
534 qe->block_proc_cls = proc_cls;
535 qe->op_id = rid;
536 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
537 h->op_tail,
538 qe);
539 env = GNUNET_MQ_msg (msg,
540 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK);
541 msg->gns_header.r_id = htonl (rid);
542 msg->query = *derived_hash;
543 GNUNET_MQ_send (h->mq,
544 env);
545 return qe;
546}
547
548
549/**
550 * Cancel a namecache operation. The final callback from the
551 * operation must not have been done yet.
552 *
553 * @param qe operation to cancel
554 */
555void
556GNUNET_NAMECACHE_cancel (struct GNUNET_NAMECACHE_QueueEntry *qe)
557{
558 struct GNUNET_NAMECACHE_Handle *h = qe->nsh;
559
560 GNUNET_CONTAINER_DLL_remove (h->op_head,
561 h->op_tail,
562 qe);
563 GNUNET_free (qe);
564}
565
566
567/* end of namecache_api.c */