aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/namestore_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/namestore_api.c')
-rw-r--r--src/namestore/namestore_api.c1307
1 files changed, 0 insertions, 1307 deletions
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
deleted file mode 100644
index b24db9b26..000000000
--- a/src/namestore/namestore_api.c
+++ /dev/null
@@ -1,1307 +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 namestore/namestore_api.c
23 * @brief API to access the NAMESTORE 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_arm_service.h"
35#include "gnunet_signatures.h"
36#include "gnunet_gns_service.h"
37#include "gnunet_namestore_service.h"
38#include "namestore.h"
39
40
41#define LOG(kind, ...) GNUNET_log_from (kind, "namestore-api", __VA_ARGS__)
42
43/**
44 * We grant the namestore up to 1 minute of latency, if it is slower than
45 * that, store queries will fail.
46 */
47#define NAMESTORE_DELAY_TOLERANCE GNUNET_TIME_UNIT_MINUTES
48
49/**
50 * An QueueEntry used to store information for a pending
51 * NAMESTORE record operation
52 */
53struct GNUNET_NAMESTORE_QueueEntry
54{
55 /**
56 * Kept in a DLL.
57 */
58 struct GNUNET_NAMESTORE_QueueEntry *next;
59
60 /**
61 * Kept in a DLL.
62 */
63 struct GNUNET_NAMESTORE_QueueEntry *prev;
64
65 /**
66 * Main handle to access the namestore.
67 */
68 struct GNUNET_NAMESTORE_Handle *h;
69
70 /**
71 * Continuation to call
72 */
73 GNUNET_NAMESTORE_ContinuationWithStatus cont;
74
75 /**
76 * Closure for @e cont.
77 */
78 void *cont_cls;
79
80 /**
81 * Function to call with the records we get back; or NULL.
82 */
83 GNUNET_NAMESTORE_RecordMonitor proc;
84
85 /**
86 * Closure for @e proc.
87 */
88 void *proc_cls;
89
90 /**
91 * Function to call on errors.
92 */
93 GNUNET_SCHEDULER_TaskCallback error_cb;
94
95 /**
96 * Closure for @e error_cb.
97 */
98 void *error_cb_cls;
99
100 /**
101 * Envelope of the message to send to the service, if not yet
102 * sent.
103 */
104 struct GNUNET_MQ_Envelope *env;
105
106 /**
107 * Task scheduled to warn us if the namestore is way too slow.
108 */
109 struct GNUNET_SCHEDULER_Task *timeout_task;
110
111 /**
112 * The operation id this zone iteration operation has
113 */
114 uint32_t op_id;
115};
116
117
118/**
119 * Handle for a zone iterator operation
120 */
121struct GNUNET_NAMESTORE_ZoneIterator
122{
123 /**
124 * Kept in a DLL.
125 */
126 struct GNUNET_NAMESTORE_ZoneIterator *next;
127
128 /**
129 * Kept in a DLL.
130 */
131 struct GNUNET_NAMESTORE_ZoneIterator *prev;
132
133 /**
134 * Main handle to access the namestore.
135 */
136 struct GNUNET_NAMESTORE_Handle *h;
137
138 /**
139 * Function to call on completion.
140 */
141 GNUNET_SCHEDULER_TaskCallback finish_cb;
142
143 /**
144 * Closure for @e error_cb.
145 */
146 void *finish_cb_cls;
147
148 /**
149 * The continuation to call with the results
150 */
151 GNUNET_NAMESTORE_RecordMonitor proc;
152
153 /**
154 * Closure for @e proc.
155 */
156 void *proc_cls;
157
158 /**
159 * Function to call on errors.
160 */
161 GNUNET_SCHEDULER_TaskCallback error_cb;
162
163 /**
164 * Closure for @e error_cb.
165 */
166 void *error_cb_cls;
167
168 /**
169 * Envelope of the message to send to the service, if not yet
170 * sent.
171 */
172 struct GNUNET_MQ_Envelope *env;
173
174 /**
175 * Private key of the zone.
176 */
177 struct GNUNET_IDENTITY_PrivateKey zone;
178
179 /**
180 * The operation id this zone iteration operation has
181 */
182 uint32_t op_id;
183};
184
185
186/**
187 * Connection to the NAMESTORE service.
188 */
189struct GNUNET_NAMESTORE_Handle
190{
191 /**
192 * Configuration to use.
193 */
194 const struct GNUNET_CONFIGURATION_Handle *cfg;
195
196 /**
197 * Connection to the service (if available).
198 */
199 struct GNUNET_MQ_Handle *mq;
200
201 /**
202 * Head of pending namestore queue entries
203 */
204 struct GNUNET_NAMESTORE_QueueEntry *op_head;
205
206 /**
207 * Tail of pending namestore queue entries
208 */
209 struct GNUNET_NAMESTORE_QueueEntry *op_tail;
210
211 /**
212 * Head of pending namestore zone iterator entries
213 */
214 struct GNUNET_NAMESTORE_ZoneIterator *z_head;
215
216 /**
217 * Tail of pending namestore zone iterator entries
218 */
219 struct GNUNET_NAMESTORE_ZoneIterator *z_tail;
220
221 /**
222 * Reconnect task
223 */
224 struct GNUNET_SCHEDULER_Task *reconnect_task;
225
226 /**
227 * Delay introduced before we reconnect.
228 */
229 struct GNUNET_TIME_Relative reconnect_delay;
230
231 /**
232 * Should we reconnect to service due to some serious error?
233 */
234 int reconnect;
235
236 /**
237 * The last operation id used for a NAMESTORE operation
238 */
239 uint32_t last_op_id_used;
240};
241
242
243/**
244 * Disconnect from service and then reconnect.
245 *
246 * @param h our handle
247 */
248static void
249force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
250
251
252/**
253 * Find the queue entry that matches the @a rid
254 *
255 * @param h namestore handle
256 * @param rid id to look up
257 * @return NULL if @a rid was not found
258 */
259static struct GNUNET_NAMESTORE_QueueEntry *
260find_qe (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid)
261{
262 struct GNUNET_NAMESTORE_QueueEntry *qe;
263
264 for (qe = h->op_head; qe != NULL; qe = qe->next)
265 if (qe->op_id == rid)
266 return qe;
267 return NULL;
268}
269
270
271/**
272 * Find the zone iteration entry that matches the @a rid
273 *
274 * @param h namestore handle
275 * @param rid id to look up
276 * @return NULL if @a rid was not found
277 */
278static struct GNUNET_NAMESTORE_ZoneIterator *
279find_zi (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid)
280{
281 struct GNUNET_NAMESTORE_ZoneIterator *ze;
282
283 for (ze = h->z_head; ze != NULL; ze = ze->next)
284 if (ze->op_id == rid)
285 return ze;
286 return NULL;
287}
288
289
290/**
291 * Free @a qe.
292 *
293 * @param qe entry to free
294 */
295static void
296free_qe (struct GNUNET_NAMESTORE_QueueEntry *qe)
297{
298 struct GNUNET_NAMESTORE_Handle *h = qe->h;
299
300 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe);
301 if (NULL != qe->env)
302 GNUNET_MQ_discard (qe->env);
303 if (NULL != qe->timeout_task)
304 GNUNET_SCHEDULER_cancel (qe->timeout_task);
305 GNUNET_free (qe);
306}
307
308
309/**
310 * Free @a ze.
311 *
312 * @param ze entry to free
313 */
314static void
315free_ze (struct GNUNET_NAMESTORE_ZoneIterator *ze)
316{
317 struct GNUNET_NAMESTORE_Handle *h = ze->h;
318
319 GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, ze);
320 if (NULL != ze->env)
321 GNUNET_MQ_discard (ze->env);
322 GNUNET_free (ze);
323}
324
325
326/**
327 * Check that @a rd_buf of length @a rd_len contains
328 * @a rd_count records.
329 *
330 * @param rd_len length of @a rd_buf
331 * @param rd_buf buffer with serialized records
332 * @param rd_count number of records expected
333 * @return #GNUNET_OK if @a rd_buf is well-formed
334 */
335static int
336check_rd (size_t rd_len, const void *rd_buf, unsigned int rd_count)
337{
338 struct GNUNET_GNSRECORD_Data rd[rd_count];
339
340 if (GNUNET_OK !=
341 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_buf, rd_count, rd))
342 {
343 GNUNET_break (0);
344 return GNUNET_SYSERR;
345 }
346 return GNUNET_OK;
347}
348
349
350/**
351 * Handle an incoming message of type
352 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
353 *
354 * @param cls
355 * @param msg the message we received
356 */
357static void
358handle_record_store_response (void *cls,
359 const struct RecordStoreResponseMessage *msg)
360{
361 struct GNUNET_NAMESTORE_Handle *h = cls;
362 struct GNUNET_NAMESTORE_QueueEntry *qe;
363 int res;
364 const char *emsg;
365
366 qe = find_qe (h, ntohl (msg->gns_header.r_id));
367 res = ntohl (msg->op_result);
368 LOG (GNUNET_ERROR_TYPE_DEBUG,
369 "Received RECORD_STORE_RESPONSE with result %d\n",
370 res);
371 /* TODO: add actual error message from namestore to response... */
372 if (GNUNET_SYSERR == res)
373 emsg = _ ("Namestore failed to store record\n");
374 else
375 emsg = NULL;
376 if (NULL == qe)
377 return;
378 if (NULL != qe->cont)
379 qe->cont (qe->cont_cls, res, emsg);
380 free_qe (qe);
381}
382
383
384/**
385 * Check validity of an incoming message of type
386 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
387 *
388 * @param cls
389 * @param msg the message we received
390 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
391 */
392static int
393check_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
394{
395 const char *name;
396 size_t exp_msg_len;
397 size_t msg_len;
398 size_t name_len;
399 size_t rd_len;
400
401 (void) cls;
402 rd_len = ntohs (msg->rd_len);
403 msg_len = ntohs (msg->gns_header.header.size);
404 name_len = ntohs (msg->name_len);
405 exp_msg_len = sizeof(*msg) + name_len + rd_len;
406 if (msg_len != exp_msg_len)
407 {
408 GNUNET_break (0);
409 return GNUNET_SYSERR;
410 }
411 name = (const char *) &msg[1];
412 if ((name_len > 0) && ('\0' != name[name_len - 1]))
413 {
414 GNUNET_break (0);
415 return GNUNET_SYSERR;
416 }
417 if (GNUNET_NO == ntohs (msg->found))
418 {
419 if (0 != ntohs (msg->rd_count))
420 {
421 GNUNET_break (0);
422 return GNUNET_SYSERR;
423 }
424 return GNUNET_OK;
425 }
426 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
427}
428
429
430/**
431 * Handle an incoming message of type
432 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
433 *
434 * @param cls
435 * @param msg the message we received
436 */
437static void
438handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
439{
440 struct GNUNET_NAMESTORE_Handle *h = cls;
441 struct GNUNET_NAMESTORE_QueueEntry *qe;
442 const char *name;
443 const char *rd_tmp;
444 size_t name_len;
445 size_t rd_len;
446 unsigned int rd_count;
447
448 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT\n");
449 qe = find_qe (h, ntohl (msg->gns_header.r_id));
450 if (NULL == qe)
451 return;
452 rd_len = ntohs (msg->rd_len);
453 rd_count = ntohs (msg->rd_count);
454 name_len = ntohs (msg->name_len);
455 name = (const char *) &msg[1];
456 if (GNUNET_NO == ntohs (msg->found))
457 {
458 /* label was not in namestore */
459 if (NULL != qe->proc)
460 qe->proc (qe->proc_cls, &msg->private_key, name, 0, NULL);
461 free_qe (qe);
462 return;
463 }
464
465 rd_tmp = &name[name_len];
466 {
467 struct GNUNET_GNSRECORD_Data rd[rd_count];
468
469 GNUNET_assert (
470 GNUNET_OK ==
471 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
472 if (0 == name_len)
473 name = NULL;
474 if (NULL != qe->proc)
475 qe->proc (qe->proc_cls,
476 &msg->private_key,
477 name,
478 rd_count,
479 (rd_count > 0) ? rd : NULL);
480 }
481 free_qe (qe);
482}
483
484
485/**
486 * Handle an incoming message of type
487 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
488 *
489 * @param cls
490 * @param msg the message we received
491 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
492 */
493static int
494check_record_result (void *cls, const struct RecordResultMessage *msg)
495{
496 static struct GNUNET_IDENTITY_PrivateKey priv_dummy;
497 const char *name;
498 size_t msg_len;
499 size_t name_len;
500 size_t rd_len;
501
502 (void) cls;
503 rd_len = ntohs (msg->rd_len);
504 msg_len = ntohs (msg->gns_header.header.size);
505 name_len = ntohs (msg->name_len);
506 if (0 != ntohs (msg->reserved))
507 {
508 GNUNET_break (0);
509 return GNUNET_SYSERR;
510 }
511 if (msg_len != sizeof(struct RecordResultMessage) + name_len + rd_len)
512 {
513 GNUNET_break (0);
514 return GNUNET_SYSERR;
515 }
516 name = (const char *) &msg[1];
517 if ((0 == name_len) || ('\0' != name[name_len - 1]))
518 {
519 GNUNET_break (0);
520 return GNUNET_SYSERR;
521 }
522 if (0 == GNUNET_memcmp (&msg->private_key, &priv_dummy))
523 {
524 GNUNET_break (0);
525 return GNUNET_SYSERR;
526 }
527 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
528}
529
530
531/**
532 * Handle an incoming message of type
533 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
534 *
535 * @param cls
536 * @param msg the message we received
537 */
538static void
539handle_record_result (void *cls, const struct RecordResultMessage *msg)
540{
541 struct GNUNET_NAMESTORE_Handle *h = cls;
542 struct GNUNET_NAMESTORE_QueueEntry *qe;
543 struct GNUNET_NAMESTORE_ZoneIterator *ze;
544 const char *name;
545 const char *rd_tmp;
546 size_t name_len;
547 size_t rd_len;
548 unsigned int rd_count;
549
550 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT\n");
551 rd_len = ntohs (msg->rd_len);
552 rd_count = ntohs (msg->rd_count);
553 name_len = ntohs (msg->name_len);
554 ze = find_zi (h, ntohl (msg->gns_header.r_id));
555 qe = find_qe (h, ntohl (msg->gns_header.r_id));
556 if ((NULL == ze) && (NULL == qe))
557 return; /* rid not found */
558 if ((NULL != ze) && (NULL != qe))
559 {
560 GNUNET_break (0); /* rid ambiguous */
561 force_reconnect (h);
562 return;
563 }
564 name = (const char *) &msg[1];
565 rd_tmp = &name[name_len];
566 {
567 struct GNUNET_GNSRECORD_Data rd[rd_count];
568
569 GNUNET_assert (
570 GNUNET_OK ==
571 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
572 if (0 == name_len)
573 name = NULL;
574 if (NULL != qe)
575 {
576 if (NULL != qe->proc)
577 qe->proc (qe->proc_cls,
578 &msg->private_key,
579 name,
580 rd_count,
581 (rd_count > 0) ? rd : NULL);
582 free_qe (qe);
583 return;
584 }
585 if (NULL != ze)
586 {
587 if (NULL != ze->proc)
588 ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd);
589 return;
590 }
591 }
592 GNUNET_assert (0);
593}
594
595
596/**
597 * Handle an incoming message of type
598 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
599 *
600 * @param cls
601 * @param msg the message we received
602 */
603static void
604handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg)
605{
606 struct GNUNET_NAMESTORE_Handle *h = cls;
607 struct GNUNET_NAMESTORE_QueueEntry *qe;
608 struct GNUNET_NAMESTORE_ZoneIterator *ze;
609
610 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT_END\n");
611 ze = find_zi (h, ntohl (msg->r_id));
612 qe = find_qe (h, ntohl (msg->r_id));
613 if ((NULL == ze) && (NULL == qe))
614 return; /* rid not found */
615 if ((NULL != ze) && (NULL != qe))
616 {
617 GNUNET_break (0); /* rid ambiguous */
618 force_reconnect (h);
619 return;
620 }
621 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n");
622 if (NULL == ze)
623 {
624 GNUNET_break (0);
625 force_reconnect (h);
626 return;
627 }
628 if (NULL != ze->finish_cb)
629 ze->finish_cb (ze->finish_cb_cls);
630 free_ze (ze);
631}
632
633
634/**
635 * Handle an incoming message of type
636 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
637 *
638 * @param qe the respective entry in the message queue
639 * @param msg the message we received
640 * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
641 */
642static int
643check_zone_to_name_response (void *cls,
644 const struct ZoneToNameResponseMessage *msg)
645{
646 size_t name_len;
647 size_t rd_ser_len;
648 const char *name_tmp;
649
650 (void) cls;
651 if (GNUNET_OK != ntohs (msg->res))
652 return GNUNET_OK;
653 name_len = ntohs (msg->name_len);
654 rd_ser_len = ntohs (msg->rd_len);
655 if (ntohs (msg->gns_header.header.size) !=
656 sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len)
657 {
658 GNUNET_break (0);
659 return GNUNET_SYSERR;
660 }
661 name_tmp = (const char *) &msg[1];
662 if ((name_len > 0) && ('\0' != name_tmp[name_len - 1]))
663 {
664 GNUNET_break (0);
665 return GNUNET_SYSERR;
666 }
667 return check_rd (rd_ser_len, &name_tmp[name_len], ntohs (msg->rd_count));
668}
669
670
671/**
672 * Handle an incoming message of type
673 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
674 *
675 * @param cls
676 * @param msg the message we received
677 */
678static void
679handle_zone_to_name_response (void *cls,
680 const struct ZoneToNameResponseMessage *msg)
681{
682 struct GNUNET_NAMESTORE_Handle *h = cls;
683 struct GNUNET_NAMESTORE_QueueEntry *qe;
684 int res;
685 size_t name_len;
686 size_t rd_ser_len;
687 unsigned int rd_count;
688 const char *name_tmp;
689 const char *rd_tmp;
690
691 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n");
692 qe = find_qe (h, ntohl (msg->gns_header.r_id));
693 if (NULL == qe)
694 {
695 LOG (GNUNET_ERROR_TYPE_WARNING,
696 "Response queue already gone...\n");
697 return;
698 }
699 res = ntohs (msg->res);
700 switch (res)
701 {
702 case GNUNET_SYSERR:
703 LOG (GNUNET_ERROR_TYPE_DEBUG,
704 "An error occurred during zone to name operation\n");
705 break;
706
707 case GNUNET_NO:
708 LOG (GNUNET_ERROR_TYPE_DEBUG,
709 "Namestore has no result for zone to name mapping \n");
710 if (NULL != qe->proc)
711 qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL);
712 free_qe (qe);
713 return;
714
715 case GNUNET_YES:
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Namestore has result for zone to name mapping \n");
718 name_len = ntohs (msg->name_len);
719 rd_count = ntohs (msg->rd_count);
720 rd_ser_len = ntohs (msg->rd_len);
721 name_tmp = (const char *) &msg[1];
722 rd_tmp = &name_tmp[name_len];
723 {
724 struct GNUNET_GNSRECORD_Data rd[rd_count];
725
726 GNUNET_assert (GNUNET_OK ==
727 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
728 rd_tmp,
729 rd_count,
730 rd));
731 /* normal end, call continuation with result */
732 if (NULL != qe->proc)
733 qe->proc (qe->proc_cls, &msg->zone, name_tmp, rd_count, rd);
734 /* return is important here: break would call continuation with error! */
735 free_qe (qe);
736 return;
737 }
738
739 default:
740 GNUNET_break (0);
741 force_reconnect (h);
742 return;
743 }
744 /* error case, call continuation with error */
745 if (NULL != qe->error_cb)
746 qe->error_cb (qe->error_cb_cls);
747 free_qe (qe);
748}
749
750
751/**
752 * Generic error handler, called with the appropriate error code and
753 * the same closure specified at the creation of the message queue.
754 * Not every message queue implementation supports an error handler.
755 *
756 * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *`
757 * @param error error code
758 */
759static void
760mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
761{
762 struct GNUNET_NAMESTORE_Handle *h = cls;
763
764 (void) error;
765 force_reconnect (h);
766}
767
768
769/**
770 * Reconnect to namestore service.
771 *
772 * @param h the handle to the NAMESTORE service
773 */
774static void
775reconnect (struct GNUNET_NAMESTORE_Handle *h)
776{
777 struct GNUNET_MQ_MessageHandler handlers[] =
778 { GNUNET_MQ_hd_fixed_size (record_store_response,
779 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
780 struct RecordStoreResponseMessage,
781 h),
782 GNUNET_MQ_hd_var_size (zone_to_name_response,
783 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
784 struct ZoneToNameResponseMessage,
785 h),
786 GNUNET_MQ_hd_var_size (record_result,
787 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
788 struct RecordResultMessage,
789 h),
790 GNUNET_MQ_hd_fixed_size (record_result_end,
791 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END,
792 struct GNUNET_NAMESTORE_Header,
793 h),
794 GNUNET_MQ_hd_var_size (lookup_result,
795 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
796 struct LabelLookupResponseMessage,
797 h),
798 GNUNET_MQ_handler_end () };
799 struct GNUNET_NAMESTORE_ZoneIterator *it;
800 struct GNUNET_NAMESTORE_QueueEntry *qe;
801
802 GNUNET_assert (NULL == h->mq);
803 h->mq =
804 GNUNET_CLIENT_connect (h->cfg, "namestore", handlers, &mq_error_handler, h);
805 if (NULL == h->mq)
806 return;
807 /* re-transmit pending requests that waited for a reconnect... */
808 for (it = h->z_head; NULL != it; it = it->next)
809 {
810 GNUNET_MQ_send (h->mq, it->env);
811 it->env = NULL;
812 }
813 for (qe = h->op_head; NULL != qe; qe = qe->next)
814 {
815 GNUNET_MQ_send (h->mq, qe->env);
816 qe->env = NULL;
817 }
818}
819
820
821/**
822 * Re-establish the connection to the service.
823 *
824 * @param cls handle to use to re-connect.
825 */
826static void
827reconnect_task (void *cls)
828{
829 struct GNUNET_NAMESTORE_Handle *h = cls;
830
831 h->reconnect_task = NULL;
832 reconnect (h);
833}
834
835
836/**
837 * Disconnect from service and then reconnect.
838 *
839 * @param h our handle
840 */
841static void
842force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
843{
844 struct GNUNET_NAMESTORE_ZoneIterator *ze;
845 struct GNUNET_NAMESTORE_QueueEntry *qe;
846
847 GNUNET_MQ_destroy (h->mq);
848 h->mq = NULL;
849 while (NULL != (ze = h->z_head))
850 {
851 if (NULL != ze->error_cb)
852 ze->error_cb (ze->error_cb_cls);
853 free_ze (ze);
854 }
855 while (NULL != (qe = h->op_head))
856 {
857 if (NULL != qe->error_cb)
858 qe->error_cb (qe->error_cb_cls);
859 if (NULL != qe->cont)
860 qe->cont (qe->cont_cls,
861 GNUNET_SYSERR,
862 "failure in communication with namestore service");
863 free_qe (qe);
864 }
865
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n");
867 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
868 h->reconnect_task =
869 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h);
870}
871
872
873/**
874 * Get a fresh operation id to distinguish between namestore requests
875 *
876 * @param h the namestore handle
877 * @return next operation id to use
878 */
879static uint32_t
880get_op_id (struct GNUNET_NAMESTORE_Handle *h)
881{
882 return h->last_op_id_used++;
883}
884
885
886/**
887 * Initialize the connection with the NAMESTORE service.
888 *
889 * @param cfg configuration to use
890 * @return handle to the GNS service, or NULL on error
891 */
892struct GNUNET_NAMESTORE_Handle *
893GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
894{
895 struct GNUNET_NAMESTORE_Handle *h;
896
897 h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
898 h->cfg = cfg;
899 reconnect (h);
900 if (NULL == h->mq)
901 {
902 GNUNET_free (h);
903 return NULL;
904 }
905 return h;
906}
907
908
909/**
910 * Disconnect from the namestore service (and free associated
911 * resources).
912 *
913 * @param h handle to the namestore
914 */
915void
916GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
917{
918 struct GNUNET_NAMESTORE_QueueEntry *q;
919 struct GNUNET_NAMESTORE_ZoneIterator *z;
920
921 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
922 GNUNET_break (NULL == h->op_head);
923 while (NULL != (q = h->op_head))
924 {
925 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
926 GNUNET_free (q);
927 }
928 GNUNET_break (NULL == h->z_head);
929 while (NULL != (z = h->z_head))
930 {
931 GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
932 GNUNET_free (z);
933 }
934 if (NULL != h->mq)
935 {
936 GNUNET_MQ_destroy (h->mq);
937 h->mq = NULL;
938 }
939 if (NULL != h->reconnect_task)
940 {
941 GNUNET_SCHEDULER_cancel (h->reconnect_task);
942 h->reconnect_task = NULL;
943 }
944 GNUNET_free (h);
945}
946
947
948/**
949 * Task launched to warn the user that the namestore is
950 * excessively slow and that a query was thus dropped.
951 *
952 * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *`
953 */
954static void
955warn_delay (void *cls)
956{
957 struct GNUNET_NAMESTORE_QueueEntry *qe = cls;
958
959 qe->timeout_task = NULL;
960 LOG (GNUNET_ERROR_TYPE_WARNING,
961 "Did not receive response from namestore after %s!\n",
962 GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE,
963 GNUNET_YES));
964 if (NULL != qe->cont)
965 {
966 qe->cont (qe->cont_cls, GNUNET_SYSERR, "timeout");
967 qe->cont = NULL;
968 }
969 GNUNET_NAMESTORE_cancel (qe);
970}
971
972
973/**
974 * Store an item in the namestore. If the item is already present,
975 * it is replaced with the new record. Use an empty array to
976 * remove all records under the given name.
977 *
978 * @param h handle to the namestore
979 * @param pkey private key of the zone
980 * @param label name that is being mapped (at most 255 characters long)
981 * @param rd_count number of records in the @a rd array
982 * @param rd array of records with data to store
983 * @param cont continuation to call when done
984 * @param cont_cls closure for @a cont
985 * @return handle to abort the request
986 */
987struct GNUNET_NAMESTORE_QueueEntry *
988GNUNET_NAMESTORE_records_store (
989 struct GNUNET_NAMESTORE_Handle *h,
990 const struct GNUNET_IDENTITY_PrivateKey *pkey,
991 const char *label,
992 unsigned int rd_count,
993 const struct GNUNET_GNSRECORD_Data *rd,
994 GNUNET_NAMESTORE_ContinuationWithStatus cont,
995 void *cont_cls)
996{
997 struct GNUNET_NAMESTORE_QueueEntry *qe;
998 struct GNUNET_MQ_Envelope *env;
999 char *name_tmp;
1000 char *rd_ser;
1001 ssize_t rd_ser_len;
1002 size_t name_len;
1003 uint32_t rid;
1004 struct RecordStoreMessage *msg;
1005 ssize_t sret;
1006
1007 name_len = strlen (label) + 1;
1008 if (name_len > MAX_NAME_LEN)
1009 {
1010 GNUNET_break (0);
1011 return NULL;
1012 }
1013 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1014 if (rd_ser_len < 0)
1015 {
1016 GNUNET_break (0);
1017 return NULL;
1018 }
1019 if (rd_ser_len > UINT16_MAX)
1020 {
1021 GNUNET_break (0);
1022 return NULL;
1023 }
1024 rid = get_op_id (h);
1025 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1026 qe->h = h;
1027 qe->cont = cont;
1028 qe->cont_cls = cont_cls;
1029 qe->op_id = rid;
1030 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1031
1032 /* setup msg */
1033 env = GNUNET_MQ_msg_extra (msg,
1034 name_len + rd_ser_len,
1035 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1036 msg->gns_header.r_id = htonl (rid);
1037 msg->name_len = htons (name_len);
1038 msg->rd_count = htons (rd_count);
1039 msg->rd_len = htons (rd_ser_len);
1040 msg->reserved = htons (0);
1041 msg->private_key = *pkey;
1042
1043 name_tmp = (char *) &msg[1];
1044 GNUNET_memcpy (name_tmp, label, name_len);
1045 rd_ser = &name_tmp[name_len];
1046 sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser);
1047 if ((0 > sret) || (sret != rd_ser_len))
1048 {
1049 GNUNET_break (0);
1050 GNUNET_free (env);
1051 return NULL;
1052 }
1053 GNUNET_assert (rd_ser_len == sret);
1054 LOG (GNUNET_ERROR_TYPE_DEBUG,
1055 "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1056 label,
1057 rd_count);
1058 qe->timeout_task =
1059 GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe);
1060 if (NULL == h->mq)
1061 {
1062 qe->env = env;
1063 LOG (GNUNET_ERROR_TYPE_WARNING,
1064 "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
1065 }
1066 else
1067 {
1068 GNUNET_MQ_send (h->mq, env);
1069 }
1070 return qe;
1071}
1072
1073
1074/**
1075 * Lookup an item in the namestore.
1076 *
1077 * @param h handle to the namestore
1078 * @param pkey private key of the zone
1079 * @param label name that is being mapped (at most 255 characters long)
1080 * @param error_cb function to call on error (i.e. disconnect)
1081 * @param error_cb_cls closure for @a error_cb
1082 * @param rm function to call with the result (with 0 records if we don't have that label)
1083 * @param rm_cls closure for @a rm
1084 * @return handle to abort the request
1085 */
1086struct GNUNET_NAMESTORE_QueueEntry *
1087GNUNET_NAMESTORE_records_lookup (
1088 struct GNUNET_NAMESTORE_Handle *h,
1089 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1090 const char *label,
1091 GNUNET_SCHEDULER_TaskCallback error_cb,
1092 void *error_cb_cls,
1093 GNUNET_NAMESTORE_RecordMonitor rm,
1094 void *rm_cls)
1095{
1096 struct GNUNET_NAMESTORE_QueueEntry *qe;
1097 struct GNUNET_MQ_Envelope *env;
1098 struct LabelLookupMessage *msg;
1099 size_t label_len;
1100
1101 if (1 == (label_len = strlen (label) + 1))
1102 {
1103 GNUNET_break (0);
1104 return NULL;
1105 }
1106
1107 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1108 qe->h = h;
1109 qe->error_cb = error_cb;
1110 qe->error_cb_cls = error_cb_cls;
1111 qe->proc = rm;
1112 qe->proc_cls = rm_cls;
1113 qe->op_id = get_op_id (h);
1114 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1115
1116 env = GNUNET_MQ_msg_extra (msg,
1117 label_len,
1118 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1119 msg->gns_header.r_id = htonl (qe->op_id);
1120 msg->zone = *pkey;
1121 msg->label_len = htonl (label_len);
1122 GNUNET_memcpy (&msg[1], label, label_len);
1123 if (NULL == h->mq)
1124 qe->env = env;
1125 else
1126 GNUNET_MQ_send (h->mq, env);
1127 return qe;
1128}
1129
1130
1131/**
1132 * Look for an existing PKEY delegation record for a given public key.
1133 * Returns at most one result to the processor.
1134 *
1135 * @param h handle to the namestore
1136 * @param zone public key of the zone to look up in, never NULL
1137 * @param value_zone public key of the target zone (value), never NULL
1138 * @param error_cb function to call on error (i.e. disconnect)
1139 * @param error_cb_cls closure for @a error_cb
1140 * @param proc function to call on the matching records, or with
1141 * NULL (rd_count == 0) if there are no matching records
1142 * @param proc_cls closure for @a proc
1143 * @return a handle that can be used to
1144 * cancel
1145 */
1146struct GNUNET_NAMESTORE_QueueEntry *
1147GNUNET_NAMESTORE_zone_to_name (
1148 struct GNUNET_NAMESTORE_Handle *h,
1149 const struct GNUNET_IDENTITY_PrivateKey *zone,
1150 const struct GNUNET_IDENTITY_PublicKey *value_zone,
1151 GNUNET_SCHEDULER_TaskCallback error_cb,
1152 void *error_cb_cls,
1153 GNUNET_NAMESTORE_RecordMonitor proc,
1154 void *proc_cls)
1155{
1156 struct GNUNET_NAMESTORE_QueueEntry *qe;
1157 struct GNUNET_MQ_Envelope *env;
1158 struct ZoneToNameMessage *msg;
1159 uint32_t rid;
1160
1161 rid = get_op_id (h);
1162 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1163 qe->h = h;
1164 qe->error_cb = error_cb;
1165 qe->error_cb_cls = error_cb_cls;
1166 qe->proc = proc;
1167 qe->proc_cls = proc_cls;
1168 qe->op_id = rid;
1169 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1170
1171 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1172 msg->gns_header.r_id = htonl (rid);
1173 msg->zone = *zone;
1174 msg->value_zone = *value_zone;
1175 if (NULL == h->mq)
1176 qe->env = env;
1177 else
1178 GNUNET_MQ_send (h->mq, env);
1179 return qe;
1180}
1181
1182
1183/**
1184 * Starts a new zone iteration (used to periodically PUT all of our
1185 * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1186 * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1187 * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1188 * immediately, and then again after
1189 * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1190 *
1191 * @param h handle to the namestore
1192 * @param zone zone to access, NULL for all zones
1193 * @param error_cb function to call on error (i.e. disconnect)
1194 * @param error_cb_cls closure for @a error_cb
1195 * @param proc function to call on each name from the zone; it
1196 * will be called repeatedly with a value (if available)
1197 * @param proc_cls closure for @a proc
1198 * @param finish_cb function to call on completion
1199 * @param finish_cb_cls closure for @a finish_cb
1200 * @return an iterator handle to use for iteration
1201 */
1202struct GNUNET_NAMESTORE_ZoneIterator *
1203GNUNET_NAMESTORE_zone_iteration_start (
1204 struct GNUNET_NAMESTORE_Handle *h,
1205 const struct GNUNET_IDENTITY_PrivateKey *zone,
1206 GNUNET_SCHEDULER_TaskCallback error_cb,
1207 void *error_cb_cls,
1208 GNUNET_NAMESTORE_RecordMonitor proc,
1209 void *proc_cls,
1210 GNUNET_SCHEDULER_TaskCallback finish_cb,
1211 void *finish_cb_cls)
1212{
1213 struct GNUNET_NAMESTORE_ZoneIterator *it;
1214 struct GNUNET_MQ_Envelope *env;
1215 struct ZoneIterationStartMessage *msg;
1216 uint32_t rid;
1217
1218 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n");
1219 rid = get_op_id (h);
1220 it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1221 it->h = h;
1222 it->error_cb = error_cb;
1223 it->error_cb_cls = error_cb_cls;
1224 it->finish_cb = finish_cb;
1225 it->finish_cb_cls = finish_cb_cls;
1226 it->proc = proc;
1227 it->proc_cls = proc_cls;
1228 it->op_id = rid;
1229 if (NULL != zone)
1230 it->zone = *zone;
1231 GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it);
1232 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1233 msg->gns_header.r_id = htonl (rid);
1234 if (NULL != zone)
1235 msg->zone = *zone;
1236 if (NULL == h->mq)
1237 it->env = env;
1238 else
1239 GNUNET_MQ_send (h->mq, env);
1240 return it;
1241}
1242
1243
1244/**
1245 * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1246 * for the next record.
1247 *
1248 * @param it the iterator
1249 * @param limit number of records to return to the iterator in one shot
1250 * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1251 */
1252void
1253GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1254 uint64_t limit)
1255{
1256 struct GNUNET_NAMESTORE_Handle *h = it->h;
1257 struct ZoneIterationNextMessage *msg;
1258 struct GNUNET_MQ_Envelope *env;
1259
1260 LOG (GNUNET_ERROR_TYPE_DEBUG,
1261 "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1262 (unsigned long long) limit);
1263 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1264 msg->gns_header.r_id = htonl (it->op_id);
1265 msg->limit = GNUNET_htonll (limit);
1266 GNUNET_MQ_send (h->mq, env);
1267}
1268
1269
1270/**
1271 * Stops iteration and releases the namestore handle for further calls.
1272 *
1273 * @param it the iterator
1274 */
1275void
1276GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1277{
1278 struct GNUNET_NAMESTORE_Handle *h = it->h;
1279 struct GNUNET_MQ_Envelope *env;
1280 struct ZoneIterationStopMessage *msg;
1281
1282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_STOP message\n");
1283 if (NULL != h->mq)
1284 {
1285 env =
1286 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1287 msg->gns_header.r_id = htonl (it->op_id);
1288 GNUNET_MQ_send (h->mq, env);
1289 }
1290 free_ze (it);
1291}
1292
1293
1294/**
1295 * Cancel a namestore operation. The final callback from the
1296 * operation must not have been done yet.
1297 *
1298 * @param qe operation to cancel
1299 */
1300void
1301GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1302{
1303 free_qe (qe);
1304}
1305
1306
1307/* end of namestore_api.c */