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.c1387
1 files changed, 0 insertions, 1387 deletions
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
deleted file mode 100644
index 73f985803..000000000
--- a/src/namestore/namestore_api.c
+++ /dev/null
@@ -1,1387 +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 * Handle an incoming message of type
351 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
352 *
353 * @param cls
354 * @param msg the message we received
355 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
356 */
357static int
358check_record_store_response (void *cls,
359 const struct RecordStoreResponseMessage *msg)
360{
361 const char *emsg;
362 size_t msg_len;
363 size_t emsg_len;
364
365 (void) cls;
366 msg_len = ntohs (msg->gns_header.header.size);
367 emsg_len = ntohs (msg->emsg_len);
368 if (0 != ntohs (msg->reserved))
369 {
370 GNUNET_break (0);
371 return GNUNET_SYSERR;
372 }
373 if (msg_len != sizeof(struct RecordStoreResponseMessage) + emsg_len)
374 {
375 GNUNET_break (0);
376 return GNUNET_SYSERR;
377 }
378 emsg = (const char *) &msg[1];
379 if ((0 != emsg_len) && ('\0' != emsg[emsg_len - 1]))
380 {
381 GNUNET_break (0);
382 return GNUNET_SYSERR;
383 }
384 return GNUNET_OK;
385}
386
387
388/**
389 * Handle an incoming message of type
390 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
391 *
392 * @param cls
393 * @param msg the message we received
394 */
395static void
396handle_record_store_response (void *cls,
397 const struct RecordStoreResponseMessage *msg)
398{
399 struct GNUNET_NAMESTORE_Handle *h = cls;
400 struct GNUNET_NAMESTORE_QueueEntry *qe;
401 int res;
402 const char *emsg;
403
404 qe = find_qe (h, ntohl (msg->gns_header.r_id));
405 emsg = (const char *) &msg[1];
406 res = ntohl (msg->op_result);
407 LOG (GNUNET_ERROR_TYPE_DEBUG,
408 "Received RECORD_STORE_RESPONSE with result %d\n",
409 res);
410 if (NULL == qe)
411 return;
412 if (NULL != qe->cont)
413 qe->cont (qe->cont_cls, res,
414 (GNUNET_OK == res) ? NULL : emsg);
415 free_qe (qe);
416}
417
418
419/**
420 * Check validity of an incoming message of type
421 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
422 *
423 * @param cls
424 * @param msg the message we received
425 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
426 */
427static int
428check_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
429{
430 const char *name;
431 size_t exp_msg_len;
432 size_t msg_len;
433 size_t name_len;
434 size_t rd_len;
435
436 (void) cls;
437 rd_len = ntohs (msg->rd_len);
438 msg_len = ntohs (msg->gns_header.header.size);
439 name_len = ntohs (msg->name_len);
440 exp_msg_len = sizeof(*msg) + name_len + rd_len;
441 if (msg_len != exp_msg_len)
442 {
443 GNUNET_break (0);
444 return GNUNET_SYSERR;
445 }
446 name = (const char *) &msg[1];
447 if ((name_len > 0) && ('\0' != name[name_len - 1]))
448 {
449 GNUNET_break (0);
450 return GNUNET_SYSERR;
451 }
452 if (GNUNET_NO == ntohs (msg->found))
453 {
454 if (0 != ntohs (msg->rd_count))
455 {
456 GNUNET_break (0);
457 return GNUNET_SYSERR;
458 }
459 return GNUNET_OK;
460 }
461 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
462}
463
464
465/**
466 * Handle an incoming message of type
467 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
468 *
469 * @param cls
470 * @param msg the message we received
471 */
472static void
473handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
474{
475 struct GNUNET_NAMESTORE_Handle *h = cls;
476 struct GNUNET_NAMESTORE_QueueEntry *qe;
477 const char *name;
478 const char *rd_tmp;
479 size_t name_len;
480 size_t rd_len;
481 unsigned int rd_count;
482 int16_t found = (int16_t) ntohs (msg->found);
483
484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n",
485 found);
486 qe = find_qe (h, ntohl (msg->gns_header.r_id));
487 if (NULL == qe)
488 return;
489 rd_len = ntohs (msg->rd_len);
490 rd_count = ntohs (msg->rd_count);
491 name_len = ntohs (msg->name_len);
492 name = (const char *) &msg[1];
493 if (GNUNET_NO == found)
494 {
495 /* label was not in namestore */
496 if (NULL != qe->proc)
497 qe->proc (qe->proc_cls, &msg->private_key, name, 0, NULL);
498 free_qe (qe);
499 return;
500 }
501 if (GNUNET_SYSERR == found)
502 {
503 if (NULL != qe->error_cb)
504 qe->error_cb (qe->error_cb_cls);
505 free_qe (qe);
506 return;
507 }
508
509 rd_tmp = &name[name_len];
510 {
511 struct GNUNET_GNSRECORD_Data rd[rd_count];
512
513 GNUNET_assert (
514 GNUNET_OK ==
515 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
516 if (0 == name_len)
517 name = NULL;
518 if (NULL != qe->proc)
519 qe->proc (qe->proc_cls,
520 &msg->private_key,
521 name,
522 rd_count,
523 (rd_count > 0) ? rd : NULL);
524 }
525 free_qe (qe);
526}
527
528
529/**
530 * Handle an incoming message of type
531 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
532 *
533 * @param cls
534 * @param msg the message we received
535 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
536 */
537static int
538check_record_result (void *cls, const struct RecordResultMessage *msg)
539{
540 static struct GNUNET_IDENTITY_PrivateKey priv_dummy;
541 const char *name;
542 size_t msg_len;
543 size_t name_len;
544 size_t rd_len;
545
546 (void) cls;
547 rd_len = ntohs (msg->rd_len);
548 msg_len = ntohs (msg->gns_header.header.size);
549 name_len = ntohs (msg->name_len);
550 if (0 != ntohs (msg->reserved))
551 {
552 GNUNET_break (0);
553 return GNUNET_SYSERR;
554 }
555 if (msg_len != sizeof(struct RecordResultMessage) + name_len + rd_len)
556 {
557 GNUNET_break (0);
558 return GNUNET_SYSERR;
559 }
560 name = (const char *) &msg[1];
561 if ((0 == name_len) || ('\0' != name[name_len - 1]))
562 {
563 GNUNET_break (0);
564 return GNUNET_SYSERR;
565 }
566 if (0 == GNUNET_memcmp (&msg->private_key, &priv_dummy))
567 {
568 GNUNET_break (0);
569 return GNUNET_SYSERR;
570 }
571 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
572}
573
574
575/**
576 * Handle an incoming message of type
577 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
578 *
579 * @param cls
580 * @param msg the message we received
581 */
582static void
583handle_record_result (void *cls, const struct RecordResultMessage *msg)
584{
585 struct GNUNET_NAMESTORE_Handle *h = cls;
586 struct GNUNET_NAMESTORE_QueueEntry *qe;
587 struct GNUNET_NAMESTORE_ZoneIterator *ze;
588 const char *name;
589 const char *rd_tmp;
590 size_t name_len;
591 size_t rd_len;
592 unsigned int rd_count;
593
594 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT\n");
595 rd_len = ntohs (msg->rd_len);
596 rd_count = ntohs (msg->rd_count);
597 name_len = ntohs (msg->name_len);
598 ze = find_zi (h, ntohl (msg->gns_header.r_id));
599 qe = find_qe (h, ntohl (msg->gns_header.r_id));
600 if ((NULL == ze) && (NULL == qe))
601 return; /* rid not found */
602 if ((NULL != ze) && (NULL != qe))
603 {
604 GNUNET_break (0); /* rid ambiguous */
605 force_reconnect (h);
606 return;
607 }
608 name = (const char *) &msg[1];
609 rd_tmp = &name[name_len];
610 {
611 struct GNUNET_GNSRECORD_Data rd[rd_count];
612
613 GNUNET_assert (
614 GNUNET_OK ==
615 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
616 if (0 == name_len)
617 name = NULL;
618 if (NULL != qe)
619 {
620 if (NULL != qe->proc)
621 qe->proc (qe->proc_cls,
622 &msg->private_key,
623 name,
624 rd_count,
625 (rd_count > 0) ? rd : NULL);
626 free_qe (qe);
627 return;
628 }
629 if (NULL != ze)
630 {
631 if (NULL != ze->proc)
632 ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd);
633 return;
634 }
635 }
636 GNUNET_assert (0);
637}
638
639
640/**
641 * Handle an incoming message of type
642 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
643 *
644 * @param cls
645 * @param msg the message we received
646 */
647static void
648handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg)
649{
650 struct GNUNET_NAMESTORE_Handle *h = cls;
651 struct GNUNET_NAMESTORE_QueueEntry *qe;
652 struct GNUNET_NAMESTORE_ZoneIterator *ze;
653
654 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT_END\n");
655 ze = find_zi (h, ntohl (msg->r_id));
656 qe = find_qe (h, ntohl (msg->r_id));
657 if ((NULL == ze) && (NULL == qe))
658 return; /* rid not found */
659 if ((NULL != ze) && (NULL != qe))
660 {
661 GNUNET_break (0); /* rid ambiguous */
662 force_reconnect (h);
663 return;
664 }
665 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n");
666 if (NULL == ze)
667 {
668 GNUNET_break (0);
669 force_reconnect (h);
670 return;
671 }
672 if (NULL != ze->finish_cb)
673 ze->finish_cb (ze->finish_cb_cls);
674 free_ze (ze);
675}
676
677
678/**
679 * Handle an incoming message of type
680 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
681 *
682 * @param qe the respective entry in the message queue
683 * @param msg the message we received
684 * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
685 */
686static int
687check_zone_to_name_response (void *cls,
688 const struct ZoneToNameResponseMessage *msg)
689{
690 size_t name_len;
691 size_t rd_ser_len;
692 const char *name_tmp;
693
694 (void) cls;
695 if (GNUNET_OK != ntohs (msg->res))
696 return GNUNET_OK;
697 name_len = ntohs (msg->name_len);
698 rd_ser_len = ntohs (msg->rd_len);
699 if (ntohs (msg->gns_header.header.size) !=
700 sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len)
701 {
702 GNUNET_break (0);
703 return GNUNET_SYSERR;
704 }
705 name_tmp = (const char *) &msg[1];
706 if ((name_len > 0) && ('\0' != name_tmp[name_len - 1]))
707 {
708 GNUNET_break (0);
709 return GNUNET_SYSERR;
710 }
711 return check_rd (rd_ser_len, &name_tmp[name_len], ntohs (msg->rd_count));
712}
713
714
715/**
716 * Handle an incoming message of type
717 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
718 *
719 * @param cls
720 * @param msg the message we received
721 */
722static void
723handle_zone_to_name_response (void *cls,
724 const struct ZoneToNameResponseMessage *msg)
725{
726 struct GNUNET_NAMESTORE_Handle *h = cls;
727 struct GNUNET_NAMESTORE_QueueEntry *qe;
728 int res;
729 size_t name_len;
730 size_t rd_ser_len;
731 unsigned int rd_count;
732 const char *name_tmp;
733 const char *rd_tmp;
734
735 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n");
736 qe = find_qe (h, ntohl (msg->gns_header.r_id));
737 if (NULL == qe)
738 {
739 LOG (GNUNET_ERROR_TYPE_WARNING,
740 "Response queue already gone...\n");
741 return;
742 }
743 res = ntohs (msg->res);
744 switch (res)
745 {
746 case GNUNET_SYSERR:
747 LOG (GNUNET_ERROR_TYPE_DEBUG,
748 "An error occurred during zone to name operation\n");
749 break;
750
751 case GNUNET_NO:
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Namestore has no result for zone to name mapping \n");
754 if (NULL != qe->proc)
755 qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL);
756 free_qe (qe);
757 return;
758
759 case GNUNET_YES:
760 LOG (GNUNET_ERROR_TYPE_DEBUG,
761 "Namestore has result for zone to name mapping \n");
762 name_len = ntohs (msg->name_len);
763 rd_count = ntohs (msg->rd_count);
764 rd_ser_len = ntohs (msg->rd_len);
765 name_tmp = (const char *) &msg[1];
766 rd_tmp = &name_tmp[name_len];
767 {
768 struct GNUNET_GNSRECORD_Data rd[rd_count];
769
770 GNUNET_assert (GNUNET_OK ==
771 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
772 rd_tmp,
773 rd_count,
774 rd));
775 /* normal end, call continuation with result */
776 if (NULL != qe->proc)
777 qe->proc (qe->proc_cls, &msg->zone, name_tmp, rd_count, rd);
778 /* return is important here: break would call continuation with error! */
779 free_qe (qe);
780 return;
781 }
782
783 default:
784 GNUNET_break (0);
785 force_reconnect (h);
786 return;
787 }
788 /* error case, call continuation with error */
789 if (NULL != qe->error_cb)
790 qe->error_cb (qe->error_cb_cls);
791 free_qe (qe);
792}
793
794
795/**
796 * Generic error handler, called with the appropriate error code and
797 * the same closure specified at the creation of the message queue.
798 * Not every message queue implementation supports an error handler.
799 *
800 * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *`
801 * @param error error code
802 */
803static void
804mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
805{
806 struct GNUNET_NAMESTORE_Handle *h = cls;
807
808 (void) error;
809 force_reconnect (h);
810}
811
812
813/**
814 * Reconnect to namestore service.
815 *
816 * @param h the handle to the NAMESTORE service
817 */
818static void
819reconnect (struct GNUNET_NAMESTORE_Handle *h)
820{
821 struct GNUNET_MQ_MessageHandler handlers[] =
822 { GNUNET_MQ_hd_var_size (record_store_response,
823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
824 struct RecordStoreResponseMessage,
825 h),
826 GNUNET_MQ_hd_var_size (zone_to_name_response,
827 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
828 struct ZoneToNameResponseMessage,
829 h),
830 GNUNET_MQ_hd_var_size (record_result,
831 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
832 struct RecordResultMessage,
833 h),
834 GNUNET_MQ_hd_fixed_size (record_result_end,
835 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END,
836 struct GNUNET_NAMESTORE_Header,
837 h),
838 GNUNET_MQ_hd_var_size (lookup_result,
839 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
840 struct LabelLookupResponseMessage,
841 h),
842 GNUNET_MQ_handler_end () };
843 struct GNUNET_NAMESTORE_ZoneIterator *it;
844 struct GNUNET_NAMESTORE_QueueEntry *qe;
845
846 GNUNET_assert (NULL == h->mq);
847 h->mq =
848 GNUNET_CLIENT_connect (h->cfg, "namestore", handlers, &mq_error_handler, h);
849 if (NULL == h->mq)
850 return;
851 /* re-transmit pending requests that waited for a reconnect... */
852 for (it = h->z_head; NULL != it; it = it->next)
853 {
854 GNUNET_MQ_send (h->mq, it->env);
855 it->env = NULL;
856 }
857 for (qe = h->op_head; NULL != qe; qe = qe->next)
858 {
859 GNUNET_MQ_send (h->mq, qe->env);
860 qe->env = NULL;
861 }
862}
863
864
865/**
866 * Re-establish the connection to the service.
867 *
868 * @param cls handle to use to re-connect.
869 */
870static void
871reconnect_task (void *cls)
872{
873 struct GNUNET_NAMESTORE_Handle *h = cls;
874
875 h->reconnect_task = NULL;
876 reconnect (h);
877}
878
879
880/**
881 * Disconnect from service and then reconnect.
882 *
883 * @param h our handle
884 */
885static void
886force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
887{
888 struct GNUNET_NAMESTORE_ZoneIterator *ze;
889 struct GNUNET_NAMESTORE_QueueEntry *qe;
890
891 GNUNET_MQ_destroy (h->mq);
892 h->mq = NULL;
893 while (NULL != (ze = h->z_head))
894 {
895 if (NULL != ze->error_cb)
896 ze->error_cb (ze->error_cb_cls);
897 free_ze (ze);
898 }
899 while (NULL != (qe = h->op_head))
900 {
901 if (NULL != qe->error_cb)
902 qe->error_cb (qe->error_cb_cls);
903 if (NULL != qe->cont)
904 qe->cont (qe->cont_cls,
905 GNUNET_SYSERR,
906 "failure in communication with namestore service");
907 free_qe (qe);
908 }
909
910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n");
911 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
912 h->reconnect_task =
913 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h);
914}
915
916
917/**
918 * Get a fresh operation id to distinguish between namestore requests
919 *
920 * @param h the namestore handle
921 * @return next operation id to use
922 */
923static uint32_t
924get_op_id (struct GNUNET_NAMESTORE_Handle *h)
925{
926 return h->last_op_id_used++;
927}
928
929
930/**
931 * Initialize the connection with the NAMESTORE service.
932 *
933 * @param cfg configuration to use
934 * @return handle to the GNS service, or NULL on error
935 */
936struct GNUNET_NAMESTORE_Handle *
937GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
938{
939 struct GNUNET_NAMESTORE_Handle *h;
940
941 h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
942 h->cfg = cfg;
943 reconnect (h);
944 if (NULL == h->mq)
945 {
946 GNUNET_free (h);
947 return NULL;
948 }
949 return h;
950}
951
952
953/**
954 * Disconnect from the namestore service (and free associated
955 * resources).
956 *
957 * @param h handle to the namestore
958 */
959void
960GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
961{
962 struct GNUNET_NAMESTORE_QueueEntry *q;
963 struct GNUNET_NAMESTORE_ZoneIterator *z;
964
965 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
966 GNUNET_break (NULL == h->op_head);
967 while (NULL != (q = h->op_head))
968 {
969 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
970 GNUNET_free (q);
971 }
972 GNUNET_break (NULL == h->z_head);
973 while (NULL != (z = h->z_head))
974 {
975 GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
976 GNUNET_free (z);
977 }
978 if (NULL != h->mq)
979 {
980 GNUNET_MQ_destroy (h->mq);
981 h->mq = NULL;
982 }
983 if (NULL != h->reconnect_task)
984 {
985 GNUNET_SCHEDULER_cancel (h->reconnect_task);
986 h->reconnect_task = NULL;
987 }
988 GNUNET_free (h);
989}
990
991
992/**
993 * Task launched to warn the user that the namestore is
994 * excessively slow and that a query was thus dropped.
995 *
996 * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *`
997 */
998static void
999warn_delay (void *cls)
1000{
1001 struct GNUNET_NAMESTORE_QueueEntry *qe = cls;
1002
1003 qe->timeout_task = NULL;
1004 LOG (GNUNET_ERROR_TYPE_WARNING,
1005 "Did not receive response from namestore after %s!\n",
1006 GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE,
1007 GNUNET_YES));
1008 if (NULL != qe->cont)
1009 {
1010 qe->cont (qe->cont_cls, GNUNET_SYSERR, "timeout");
1011 qe->cont = NULL;
1012 }
1013 GNUNET_NAMESTORE_cancel (qe);
1014}
1015
1016
1017struct GNUNET_NAMESTORE_QueueEntry *
1018GNUNET_NAMESTORE_records_store (
1019 struct GNUNET_NAMESTORE_Handle *h,
1020 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1021 const char *label,
1022 unsigned int rd_count,
1023 const struct GNUNET_GNSRECORD_Data *rd,
1024 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1025 void *cont_cls)
1026{
1027 struct GNUNET_NAMESTORE_QueueEntry *qe;
1028 struct GNUNET_MQ_Envelope *env;
1029 char *name_tmp;
1030 char *rd_ser;
1031 ssize_t rd_ser_len;
1032 size_t name_len;
1033 uint32_t rid;
1034 struct RecordStoreMessage *msg;
1035 ssize_t sret;
1036
1037 name_len = strlen (label) + 1;
1038 if (name_len > MAX_NAME_LEN)
1039 {
1040 GNUNET_break (0);
1041 return NULL;
1042 }
1043 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1044 if (rd_ser_len < 0)
1045 {
1046 GNUNET_break (0);
1047 return NULL;
1048 }
1049 if (rd_ser_len > UINT16_MAX)
1050 {
1051 GNUNET_break (0);
1052 return NULL;
1053 }
1054 rid = get_op_id (h);
1055 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1056 qe->h = h;
1057 qe->cont = cont;
1058 qe->cont_cls = cont_cls;
1059 qe->op_id = rid;
1060 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1061
1062 /* setup msg */
1063 env = GNUNET_MQ_msg_extra (msg,
1064 name_len + rd_ser_len,
1065 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1066 msg->gns_header.r_id = htonl (rid);
1067 msg->name_len = htons (name_len);
1068 msg->rd_count = htons (rd_count);
1069 msg->rd_len = htons (rd_ser_len);
1070 msg->reserved = ntohs (0);
1071 msg->private_key = *pkey;
1072
1073 name_tmp = (char *) &msg[1];
1074 GNUNET_memcpy (name_tmp, label, name_len);
1075 rd_ser = &name_tmp[name_len];
1076 sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser);
1077 if ((0 > sret) || (sret != rd_ser_len))
1078 {
1079 GNUNET_break (0);
1080 GNUNET_free (env);
1081 return NULL;
1082 }
1083 GNUNET_assert (rd_ser_len == sret);
1084 LOG (GNUNET_ERROR_TYPE_DEBUG,
1085 "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1086 label,
1087 rd_count);
1088 qe->timeout_task =
1089 GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe);
1090 if (NULL == h->mq)
1091 {
1092 qe->env = env;
1093 LOG (GNUNET_ERROR_TYPE_WARNING,
1094 "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
1095 }
1096 else
1097 {
1098 GNUNET_MQ_send (h->mq, env);
1099 }
1100 return qe;
1101}
1102
1103/**
1104 * TODO: Experimental API will replace API above.
1105 */
1106struct GNUNET_NAMESTORE_QueueEntry *
1107GNUNET_NAMESTORE_records_replace (
1108 struct GNUNET_NAMESTORE_Handle *h,
1109 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1110 const char *label,
1111 unsigned int rd_count,
1112 const struct GNUNET_GNSRECORD_Data *rd,
1113 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1114 void *cont_cls)
1115{
1116 return GNUNET_NAMESTORE_records_store (h, pkey, label, rd_count, rd,
1117 cont, cont_cls);
1118}
1119
1120struct GNUNET_NAMESTORE_QueueEntry *
1121GNUNET_NAMESTORE_records_lookup (
1122 struct GNUNET_NAMESTORE_Handle *h,
1123 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1124 const char *label,
1125 GNUNET_SCHEDULER_TaskCallback error_cb,
1126 void *error_cb_cls,
1127 GNUNET_NAMESTORE_RecordMonitor rm,
1128 void *rm_cls)
1129{
1130 struct GNUNET_NAMESTORE_QueueEntry *qe;
1131 struct GNUNET_MQ_Envelope *env;
1132 struct LabelLookupMessage *msg;
1133 size_t label_len;
1134
1135 if (1 == (label_len = strlen (label) + 1))
1136 {
1137 GNUNET_break (0);
1138 return NULL;
1139 }
1140
1141 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1142 qe->h = h;
1143 qe->error_cb = error_cb;
1144 qe->error_cb_cls = error_cb_cls;
1145 qe->proc = rm;
1146 qe->proc_cls = rm_cls;
1147 qe->op_id = get_op_id (h);
1148 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1149
1150 env = GNUNET_MQ_msg_extra (msg,
1151 label_len,
1152 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1153 msg->gns_header.r_id = htonl (qe->op_id);
1154 msg->zone = *pkey;
1155 msg->label_len = htonl (label_len);
1156 GNUNET_memcpy (&msg[1], label, label_len);
1157 if (NULL == h->mq)
1158 qe->env = env;
1159 else
1160 GNUNET_MQ_send (h->mq, env);
1161 return qe;
1162}
1163
1164
1165/**
1166 * TODO experimental API. Will replace old API above.
1167 */
1168struct GNUNET_NAMESTORE_QueueEntry *
1169GNUNET_NAMESTORE_records_select (
1170 struct GNUNET_NAMESTORE_Handle *h,
1171 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1172 const char *label,
1173 GNUNET_SCHEDULER_TaskCallback error_cb,
1174 void *error_cb_cls,
1175 GNUNET_NAMESTORE_RecordMonitor rm,
1176 void *rm_cls)
1177{
1178 return GNUNET_NAMESTORE_records_lookup (h, pkey, label,
1179 error_cb, error_cb_cls,
1180 rm, rm_cls);
1181}
1182
1183struct GNUNET_NAMESTORE_QueueEntry *
1184GNUNET_NAMESTORE_zone_to_name (
1185 struct GNUNET_NAMESTORE_Handle *h,
1186 const struct GNUNET_IDENTITY_PrivateKey *zone,
1187 const struct GNUNET_IDENTITY_PublicKey *value_zone,
1188 GNUNET_SCHEDULER_TaskCallback error_cb,
1189 void *error_cb_cls,
1190 GNUNET_NAMESTORE_RecordMonitor proc,
1191 void *proc_cls)
1192{
1193 struct GNUNET_NAMESTORE_QueueEntry *qe;
1194 struct GNUNET_MQ_Envelope *env;
1195 struct ZoneToNameMessage *msg;
1196 uint32_t rid;
1197
1198 rid = get_op_id (h);
1199 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1200 qe->h = h;
1201 qe->error_cb = error_cb;
1202 qe->error_cb_cls = error_cb_cls;
1203 qe->proc = proc;
1204 qe->proc_cls = proc_cls;
1205 qe->op_id = rid;
1206 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1207
1208 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1209 msg->gns_header.r_id = htonl (rid);
1210 msg->zone = *zone;
1211 msg->value_zone = *value_zone;
1212 if (NULL == h->mq)
1213 qe->env = env;
1214 else
1215 GNUNET_MQ_send (h->mq, env);
1216 return qe;
1217}
1218
1219
1220/**
1221 * Starts a new zone iteration (used to periodically PUT all of our
1222 * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1223 * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1224 * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1225 * immediately, and then again after
1226 * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1227 *
1228 * @param h handle to the namestore
1229 * @param zone zone to access, NULL for all zones
1230 * @param error_cb function to call on error (i.e. disconnect)
1231 * @param error_cb_cls closure for @a error_cb
1232 * @param proc function to call on each name from the zone; it
1233 * will be called repeatedly with a value (if available)
1234 * @param proc_cls closure for @a proc
1235 * @param finish_cb function to call on completion
1236 * @param finish_cb_cls closure for @a finish_cb
1237 * @return an iterator handle to use for iteration
1238 */
1239struct GNUNET_NAMESTORE_ZoneIterator *
1240GNUNET_NAMESTORE_zone_iteration_start (
1241 struct GNUNET_NAMESTORE_Handle *h,
1242 const struct GNUNET_IDENTITY_PrivateKey *zone,
1243 GNUNET_SCHEDULER_TaskCallback error_cb,
1244 void *error_cb_cls,
1245 GNUNET_NAMESTORE_RecordMonitor proc,
1246 void *proc_cls,
1247 GNUNET_SCHEDULER_TaskCallback finish_cb,
1248 void *finish_cb_cls)
1249{
1250 struct GNUNET_NAMESTORE_ZoneIterator *it;
1251 struct GNUNET_MQ_Envelope *env;
1252 struct ZoneIterationStartMessage *msg;
1253 uint32_t rid;
1254
1255 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n");
1256 rid = get_op_id (h);
1257 it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1258 it->h = h;
1259 it->error_cb = error_cb;
1260 it->error_cb_cls = error_cb_cls;
1261 it->finish_cb = finish_cb;
1262 it->finish_cb_cls = finish_cb_cls;
1263 it->proc = proc;
1264 it->proc_cls = proc_cls;
1265 it->op_id = rid;
1266 if (NULL != zone)
1267 it->zone = *zone;
1268 GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it);
1269 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1270 msg->gns_header.r_id = htonl (rid);
1271 if (NULL != zone)
1272 msg->zone = *zone;
1273 if (NULL == h->mq)
1274 it->env = env;
1275 else
1276 GNUNET_MQ_send (h->mq, env);
1277 return it;
1278}
1279
1280
1281/**
1282 * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1283 * for the next record.
1284 *
1285 * @param it the iterator
1286 * @param limit number of records to return to the iterator in one shot
1287 * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1288 */
1289void
1290GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1291 uint64_t limit)
1292{
1293 struct GNUNET_NAMESTORE_Handle *h = it->h;
1294 struct ZoneIterationNextMessage *msg;
1295 struct GNUNET_MQ_Envelope *env;
1296
1297 LOG (GNUNET_ERROR_TYPE_DEBUG,
1298 "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1299 (unsigned long long) limit);
1300 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1301 msg->gns_header.r_id = htonl (it->op_id);
1302 msg->limit = GNUNET_htonll (limit);
1303 GNUNET_MQ_send (h->mq, env);
1304}
1305
1306
1307/**
1308 * Stops iteration and releases the namestore handle for further calls.
1309 *
1310 * @param it the iterator
1311 */
1312void
1313GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1314{
1315 struct GNUNET_NAMESTORE_Handle *h = it->h;
1316 struct GNUNET_MQ_Envelope *env;
1317 struct ZoneIterationStopMessage *msg;
1318
1319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_STOP message\n");
1320 if (NULL != h->mq)
1321 {
1322 env =
1323 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1324 msg->gns_header.r_id = htonl (it->op_id);
1325 GNUNET_MQ_send (h->mq, env);
1326 }
1327 free_ze (it);
1328}
1329
1330
1331/**
1332 * Cancel a namestore operation. The final callback from the
1333 * operation must not have been done yet.
1334 *
1335 * @param qe operation to cancel
1336 */
1337void
1338GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1339{
1340 free_qe (qe);
1341}
1342
1343/**
1344 * New API draft. Experimental
1345 */
1346
1347struct GNUNET_NAMESTORE_QueueEntry *
1348GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
1349 GNUNET_SCHEDULER_TaskCallback error_cb,
1350 void *error_cb_cls)
1351{
1352 GNUNET_break (0);
1353 return NULL;
1354}
1355
1356
1357struct GNUNET_NAMESTORE_QueueEntry *
1358GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h,
1359 GNUNET_SCHEDULER_TaskCallback error_cb,
1360 void *error_cb_cls)
1361{
1362 GNUNET_break (0);
1363 return NULL;
1364}
1365
1366
1367/**
1368 * Commit a namestore transaction.
1369 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
1370 *
1371 * @param h handle to the namestore
1372 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
1373 * the handle is afterwards invalid
1374 * @param error_cb_cls closure for @a error_cb
1375 * @return handle to abort the request
1376 */
1377struct GNUNET_NAMESTORE_QueueEntry *
1378GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
1379 GNUNET_SCHEDULER_TaskCallback error_cb,
1380 void *error_cb_cls)
1381{
1382 GNUNET_break (0);
1383 return NULL;
1384}
1385
1386
1387/* end of namestore_api.c */