aboutsummaryrefslogtreecommitdiff
path: root/src/service/namestore/gnunet-service-namestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/namestore/gnunet-service-namestore.c')
-rw-r--r--src/service/namestore/gnunet-service-namestore.c2752
1 files changed, 2752 insertions, 0 deletions
diff --git a/src/service/namestore/gnunet-service-namestore.c b/src/service/namestore/gnunet-service-namestore.c
new file mode 100644
index 000000000..26de295bf
--- /dev/null
+++ b/src/service/namestore/gnunet-service-namestore.c
@@ -0,0 +1,2752 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2018 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/gnunet-service-namestore.c
23 * @brief namestore for the GNUnet naming system
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gns_service.h"
30#include "gnunet_namestore_service.h"
31#include "gnunet_namestore_plugin.h"
32#include "gnunet_statistics_service.h"
33#include "gnunet_signatures.h"
34#include "namestore.h"
35
36#define LOG_STRERROR_FILE(kind, syscall, filename) \
37 GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
38
39/**
40 * If a monitor takes more than 1 minute to process an event, print a warning.
41 */
42#define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
43
44/**
45 * Size of the cache used by #get_nick_record()
46 */
47#define NC_SIZE 16
48
49/**
50 * A namestore client
51 */
52struct NamestoreClient;
53
54
55/**
56 * A namestore iteration operation.
57 */
58struct ZoneIteration
59{
60 /**
61 * Next element in the DLL
62 */
63 struct ZoneIteration *next;
64
65 /**
66 * Previous element in the DLL
67 */
68 struct ZoneIteration *prev;
69
70 /**
71 * Namestore client which intiated this zone iteration
72 */
73 struct NamestoreClient *nc;
74
75 /**
76 * The nick to add to the records
77 */
78 struct GNUNET_GNSRECORD_Data *nick;
79
80 /**
81 * Key of the zone we are iterating over.
82 */
83 struct GNUNET_CRYPTO_PrivateKey zone;
84
85 /**
86 * The record set filter
87 */
88 enum GNUNET_GNSRECORD_Filter filter;
89
90 /**
91 * Last sequence number in the zone iteration used to address next
92 * result of the zone iteration in the store
93 *
94 * Initially set to 0.
95 * Updated in #zone_iterate_proc()
96 */
97 uint64_t seq;
98
99 /**
100 * The operation id for the zone iteration in the response for the client
101 */
102 uint32_t request_id;
103
104 /**
105 * Offset of the zone iteration used to address next result of the zone
106 * iteration in the store
107 *
108 * Initially set to 0 in #handle_iteration_start
109 * Incremented with by every call to #handle_iteration_next
110 */
111 uint32_t offset;
112
113 /**
114 * Number of pending cache operations triggered by this zone iteration which we
115 * need to wait for before allowing the client to continue.
116 */
117 unsigned int cache_ops;
118
119 /**
120 * Set to #GNUNET_YES if the last iteration exhausted the limit set by the
121 * client and we should send the #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
122 * message and free the data structure once @e cache_ops is zero.
123 */
124 int send_end;
125};
126
127/**
128 * A namestore client
129 */
130struct NamestoreClient
131{
132 /**
133 * The client
134 */
135 struct GNUNET_SERVICE_Client *client;
136
137 /**
138 * Database handle for client
139 */
140 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
141
142 /**
143 * Name of loaded plugin (neeed for cleanup)
144 */
145 char *db_lib_name;
146
147 /**
148 * GNUNET_YES if this nc has begun a transaction which is uncommited.
149 */
150 int in_transaction;
151
152 /**
153 * Message queue for transmission to @e client
154 */
155 struct GNUNET_MQ_Handle *mq;
156
157 /**
158 * Head of the DLL of
159 * Zone iteration operations in progress initiated by this client
160 */
161 struct ZoneIteration *op_head;
162
163 /**
164 * Tail of the DLL of
165 * Zone iteration operations in progress initiated by this client
166 */
167 struct ZoneIteration *op_tail;
168};
169
170
171/**
172 * A namestore monitor.
173 */
174struct ZoneMonitor
175{
176 /**
177 * Next element in the DLL
178 */
179 struct ZoneMonitor *next;
180
181 /**
182 * Previous element in the DLL
183 */
184 struct ZoneMonitor *prev;
185
186 /**
187 * Namestore client which intiated this zone monitor
188 */
189 struct NamestoreClient *nc;
190
191 /**
192 * Private key of the zone.
193 */
194 struct GNUNET_CRYPTO_PrivateKey zone;
195
196 /**
197 * The record set filter
198 */
199 enum GNUNET_GNSRECORD_Filter filter;
200
201 /**
202 * Task active during initial iteration.
203 */
204 struct GNUNET_SCHEDULER_Task *task;
205
206 /**
207 * Task to warn about slow monitors.
208 */
209 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
210
211 /**
212 * Since when are we blocked on this monitor?
213 */
214 struct GNUNET_TIME_Absolute sa_waiting_start;
215
216 /**
217 * Last sequence number in the zone iteration used to address next
218 * result of the zone iteration in the store
219 *
220 * Initially set to 0.
221 * Updated in #monitor_iterate_cb()
222 */
223 uint64_t seq;
224
225 /**
226 * Current limit of how many more messages we are allowed
227 * to queue to this monitor.
228 */
229 uint64_t limit;
230
231 /**
232 * How many more requests may we receive from the iterator
233 * before it is at the limit we gave it? Will be below or
234 * equal to @e limit. The effective limit for monitor
235 * events is thus @e iteration_cnt - @e limit!
236 */
237 uint64_t iteration_cnt;
238
239 /**
240 * Are we (still) in the initial iteration pass?
241 */
242 int in_first_iteration;
243
244 /**
245 * Run again because we skipped an orphan
246 */
247 int run_again;
248
249 /**
250 * Is there a store activity waiting for this monitor? We only raise the
251 * flag when it happens and search the DLL for the store activity when we
252 * had a limit increase. If we cannot find any waiting store activity at
253 * that time, we clear the flag again.
254 */
255 int sa_waiting;
256};
257
258
259
260/**
261 * Information for an ongoing #handle_record_store() operation.
262 * Needed as we may wait for monitors to be ready for the notification.
263 */
264struct StoreActivity
265{
266 /**
267 * Kept in a DLL.
268 */
269 struct StoreActivity *next;
270
271 /**
272 * Kept in a DLL.
273 */
274 struct StoreActivity *prev;
275
276 /**
277 * Which client triggered the store activity?
278 */
279 struct NamestoreClient *nc;
280
281 /**
282 * The request ID
283 */
284 uint32_t rid;
285
286 /**
287 * The currently processed record
288 */
289 uint16_t rd_set_pos;
290
291 /**
292 * The number of records in this activity
293 */
294 uint16_t rd_set_count;
295
296 /**
297 * Wheather or not this store action is already commited.
298 * The store activity will not be processed unless this field is GNUNET_YES
299 */
300 int uncommited;
301
302 /**
303 * The zone private key
304 */
305 struct GNUNET_CRYPTO_PrivateKey private_key;
306
307 /**
308 * Copy of the original record set (as data fields in @e rd will
309 * point into it!).
310 */
311 const struct RecordSet *rs;
312
313 /**
314 * Next zone monitor that still needs to be notified about this PUT.
315 */
316 struct ZoneMonitor *zm_pos;
317
318};
319
320
321/**
322 * Entry in list of cached nick resolutions.
323 */
324struct NickCache
325{
326 /**
327 * Zone the cache entry is for.
328 */
329 struct GNUNET_CRYPTO_PrivateKey zone;
330
331 /**
332 * Cached record data.
333 */
334 struct GNUNET_GNSRECORD_Data *rd;
335
336 /**
337 * Timestamp when this cache entry was used last.
338 */
339 struct GNUNET_TIME_Absolute last_used;
340};
341
342/**
343 * We cache nick records to reduce DB load.
344 */
345static struct NickCache nick_cache[NC_SIZE];
346
347/**
348 * Public key of all zeros.
349 */
350static const struct GNUNET_CRYPTO_PrivateKey zero;
351
352/**
353 * Configuration handle.
354 */
355static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
356
357/**
358 * Handle to the statistics service
359 */
360static struct GNUNET_STATISTICS_Handle *statistics;
361
362/**
363 * Name of the database plugin
364 */
365static char *db_lib_name;
366
367/**
368 * Database handle for service
369 */
370struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
371
372
373/**
374 * First active zone monitor.
375 */
376static struct ZoneMonitor *monitor_head;
377
378/**
379 * Last active zone monitor.
380 */
381static struct ZoneMonitor *monitor_tail;
382
383/**
384 * Head of DLL of monitor-blocked store activities.
385 */
386static struct StoreActivity *sa_head;
387
388/**
389 * Tail of DLL of monitor-blocked store activities.
390 */
391static struct StoreActivity *sa_tail;
392
393/**
394 * Notification context shared by all monitors.
395 */
396static struct GNUNET_NotificationContext *monitor_nc;
397
398/**
399 * Returned orphaned records?
400 */
401static int return_orphaned;
402
403/**
404 * Task run during shutdown.
405 *
406 * @param cls unused
407 */
408static void
409cleanup_task (void *cls)
410{
411 (void) cls;
412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
413 if (NULL != monitor_nc)
414 {
415 GNUNET_notification_context_destroy (monitor_nc);
416 monitor_nc = NULL;
417 }
418 if (NULL != statistics)
419 {
420 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
421 statistics = NULL;
422 }
423 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
424 GNUNET_free (db_lib_name);
425 db_lib_name = NULL;
426}
427
428
429/**
430 * Release memory used by @a sa.
431 *
432 * @param sa activity to free
433 */
434static void
435free_store_activity (struct StoreActivity *sa)
436{
437 GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa);
438 GNUNET_free (sa);
439}
440
441/**
442 * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT
443 * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
444 * record, which (if found) is then copied to @a cls for future use.
445 *
446 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
447 * @param seq sequence number of the record, MUST NOT BE ZERO
448 * @param private_key the private key of the zone (unused)
449 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
450 * @param rd_count number of records in @a rd
451 * @param rd records stored under @a label in the zone
452 */
453static void
454lookup_nick_it (void *cls,
455 uint64_t seq,
456 const struct GNUNET_CRYPTO_PrivateKey *private_key,
457 const char *label,
458 unsigned int rd_count,
459 const struct GNUNET_GNSRECORD_Data *rd)
460{
461 struct GNUNET_GNSRECORD_Data **res = cls;
462
463 (void) private_key;
464 GNUNET_assert (0 != seq);
465 if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
466 {
467 GNUNET_break (0);
468 return;
469 }
470 for (unsigned int c = 0; c < rd_count; c++)
471 {
472 if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
473 {
474 (*res) =
475 GNUNET_malloc (rd[c].data_size + sizeof(struct GNUNET_GNSRECORD_Data));
476 (*res)->data = &(*res)[1];
477 GNUNET_memcpy ((void *) (*res)->data, rd[c].data, rd[c].data_size);
478 (*res)->data_size = rd[c].data_size;
479 (*res)->expiration_time = rd[c].expiration_time;
480 (*res)->flags = rd[c].flags;
481 (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
482 return;
483 }
484 }
485 (*res) = NULL;
486}
487
488
489/**
490 * Add entry to the cache for @a zone and @a nick
491 *
492 * @param zone zone key to cache under
493 * @param nick nick entry to cache
494 */
495static void
496cache_nick (const struct GNUNET_CRYPTO_PrivateKey *zone,
497 const struct GNUNET_GNSRECORD_Data *nick)
498{
499 struct NickCache *oldest;
500
501 oldest = NULL;
502 for (unsigned int i = 0; i < NC_SIZE; i++)
503 {
504 struct NickCache *pos = &nick_cache[i];
505
506 if ((NULL == oldest) ||
507 (oldest->last_used.abs_value_us > pos->last_used.abs_value_us))
508 oldest = pos;
509 if (0 == GNUNET_memcmp (zone, &pos->zone))
510 {
511 oldest = pos;
512 break;
513 }
514 }
515 GNUNET_free (oldest->rd);
516 oldest->zone = *zone;
517 if (NULL != nick)
518 {
519 oldest->rd = GNUNET_malloc (sizeof(*nick) + nick->data_size);
520 *oldest->rd = *nick;
521 oldest->rd->data = &oldest->rd[1];
522 memcpy (&oldest->rd[1], nick->data, nick->data_size);
523 }
524 else
525 {
526 oldest->rd = NULL;
527 }
528 oldest->last_used = GNUNET_TIME_absolute_get ();
529}
530
531
532/**
533 * Return the NICK record for the zone (if it exists).
534 *
535 * @param nc the namestore client
536 * @param zone private key for the zone to look for nick
537 * @return NULL if no NICK record was found
538 */
539static struct GNUNET_GNSRECORD_Data *
540get_nick_record (const struct GNUNET_CRYPTO_PrivateKey *zone)
541{
542 struct GNUNET_CRYPTO_PublicKey pub;
543 struct GNUNET_GNSRECORD_Data *nick;
544 int res;
545
546 /* check cache first */
547 for (unsigned int i = 0; i < NC_SIZE; i++)
548 {
549 struct NickCache *pos = &nick_cache[i];
550 if ((NULL != pos->rd) && (0 == GNUNET_memcmp (zone, &pos->zone)))
551 {
552 if (NULL == pos->rd)
553 return NULL;
554 nick = GNUNET_malloc (sizeof(*nick) + pos->rd->data_size);
555 *nick = *pos->rd;
556 nick->data = &nick[1];
557 memcpy (&nick[1], pos->rd->data, pos->rd->data_size);
558 pos->last_used = GNUNET_TIME_absolute_get ();
559 return nick;
560 }
561 }
562
563 nick = NULL;
564 res = GSN_database->lookup_records (GSN_database->cls,
565 zone,
566 GNUNET_GNS_EMPTY_LABEL_AT,
567 &lookup_nick_it,
568 &nick);
569 if ((GNUNET_OK != res) || (NULL == nick))
570 {
571#if ! defined(GNUNET_CULL_LOGGING)
572 static int do_log = GNUNET_LOG_CALL_STATUS;
573
574 if (0 == do_log)
575 do_log = GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_DEBUG,
576 "namestore",
577 __FILE__,
578 __FUNCTION__,
579 __LINE__);
580 if (1 == do_log)
581 {
582 GNUNET_CRYPTO_key_get_public (zone, &pub);
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
584 "No nick name set for zone `%s'\n",
585 GNUNET_GNSRECORD_z2s (&pub));
586 }
587#endif
588 /* update cache */
589 cache_nick (zone, NULL);
590 return NULL;
591 }
592
593 /* update cache */
594 cache_nick (zone, nick);
595 return nick;
596}
597
598
599/**
600 * Merge the nick record @a nick_rd with the rest of the
601 * record set given in @a rd2. Store the result in @a rdc_res
602 * and @a rd_res. The @a nick_rd's expiration time is set to
603 * the maximum expiration time of all of the records in @a rd2.
604 *
605 * @param nick_rd the nick record to integrate
606 * @param rd2_length length of the @a rd2 array
607 * @param rd2 array of records
608 * @param[out] rdc_res length of the resulting @a rd_res array
609 * @param[out] rd_res set to an array of records,
610 * including @a nick_rd and @a rd2;
611 * all of the variable-size 'data' fields in @a rd2 are
612 * allocated in the same chunk of memory!
613 */
614static void
615merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
616 unsigned int rd2_length,
617 const struct GNUNET_GNSRECORD_Data *rd2,
618 unsigned int *rdc_res,
619 struct GNUNET_GNSRECORD_Data **rd_res)
620{
621 uint64_t latest_expiration;
622 size_t req;
623 char *data;
624 size_t data_offset;
625 struct GNUNET_GNSRECORD_Data *target;
626
627 (*rdc_res) = 1 + rd2_length;
628 if (0 == 1 + rd2_length)
629 {
630 GNUNET_break (0);
631 (*rd_res) = NULL;
632 return;
633 }
634 req = sizeof(struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
635 for (unsigned int i = 0; i < rd2_length; i++)
636 {
637 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
638
639 if (req + sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
640 {
641 GNUNET_break (0);
642 (*rd_res) = NULL;
643 return;
644 }
645 req += sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size;
646 }
647 target = GNUNET_malloc (req);
648 (*rd_res) = target;
649 data = (char *) &target[1 + rd2_length];
650 data_offset = 0;
651 latest_expiration = 0;
652 for (unsigned int i = 0; i < rd2_length; i++)
653 {
654 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
655
656 if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
657 {
658 if ((GNUNET_TIME_absolute_get ().abs_value_us + orig->expiration_time) >
659 latest_expiration)
660 latest_expiration = orig->expiration_time;
661 }
662 else if (orig->expiration_time > latest_expiration)
663 latest_expiration = orig->expiration_time;
664 target[i] = *orig;
665 target[i].data = (void *) &data[data_offset];
666 GNUNET_memcpy (&data[data_offset], orig->data, orig->data_size);
667 data_offset += orig->data_size;
668 }
669 /* append nick */
670 target[rd2_length] = *nick_rd;
671 /* Mark as supplemental */
672 target[rd2_length].flags = nick_rd->flags | GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
673 target[rd2_length].expiration_time = latest_expiration;
674 target[rd2_length].data = (void *) &data[data_offset];
675 GNUNET_memcpy (&data[data_offset], nick_rd->data, nick_rd->data_size);
676 data_offset += nick_rd->data_size;
677 GNUNET_assert (req == (sizeof(struct GNUNET_GNSRECORD_Data)) * (*rdc_res)
678 + data_offset);
679}
680
681
682/**
683 * Generate a `struct LookupNameResponseMessage` and send it to the
684 * given client using the given notification context.
685 *
686 * @param nc client to unicast to
687 * @param request_id request ID to use
688 * @param zone_key zone key of the zone
689 * @param name name
690 * @param rd_count number of records in @a rd
691 * @param rd array of records
692 * @param filter record set filter
693 */
694static int
695send_lookup_response_with_filter (struct NamestoreClient *nc,
696 uint32_t request_id,
697 const struct
698 GNUNET_CRYPTO_PrivateKey *zone_key,
699 const char *name,
700 unsigned int rd_count,
701 const struct GNUNET_GNSRECORD_Data *rd,
702 enum GNUNET_GNSRECORD_Filter filter)
703{
704 struct GNUNET_MQ_Envelope *env;
705 struct RecordResultMessage *zir_msg;
706 struct GNUNET_GNSRECORD_Data *nick;
707 struct GNUNET_GNSRECORD_Data *res;
708 struct GNUNET_GNSRECORD_Data rd_nf[rd_count];
709 struct GNUNET_TIME_Absolute block_exp = GNUNET_TIME_UNIT_ZERO_ABS;;
710 unsigned int res_count;
711 unsigned int rd_nf_count;
712 size_t name_len;
713 size_t key_len;
714 ssize_t rd_ser_len;
715 char *name_tmp;
716 char *rd_ser;
717 char *emsg;
718
719 nick = get_nick_record (zone_key);
720 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
721
722 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (name,
723 rd,
724 rd_count,
725 rd_nf,
726 &rd_nf_count,
727 &block_exp,
728 filter,
729 &emsg))
730 {
731 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
732 GNUNET_free (emsg);
733 GNUNET_assert (0);
734 }
735
736 /**
737 * FIXME if we ever support GNUNET_NAMESTORE_OMIT_PUBLIC,
738 * we need to omit adding this public record here
739 */
740 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
741 {
742 nick->flags =
743 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
744 merge_with_nick_records (nick, rd_nf_count, rd_nf, &res_count, &res);
745 }
746 else
747 {
748 res_count = rd_nf_count;
749 res = (struct GNUNET_GNSRECORD_Data *) rd_nf;
750 }
751 if (NULL != nick)
752 GNUNET_free (nick);
753
754 if (0 == res_count)
755 {
756 if (rd_nf != res)
757 GNUNET_free (res);
758 return 0;
759 }
760 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res));
761
762
763 name_len = strlen (name) + 1;
764 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
765 if (rd_ser_len < 0)
766 {
767 if (rd_nf != res)
768 GNUNET_free (res);
769 GNUNET_break (0);
770 GNUNET_SERVICE_client_drop (nc->client);
771 return 0;
772 }
773 if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg))
774 {
775 if (rd_nf != res)
776 GNUNET_free (res);
777 GNUNET_break (0);
778 GNUNET_SERVICE_client_drop (nc->client);
779 return 0;
780 }
781 key_len = GNUNET_CRYPTO_private_key_get_length (zone_key);
782 env = GNUNET_MQ_msg_extra (zir_msg,
783 name_len + rd_ser_len + key_len,
784 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
785 zir_msg->gns_header.r_id = htonl (request_id);
786 zir_msg->name_len = htons (name_len);
787 zir_msg->rd_count = htons (res_count);
788 zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
789 zir_msg->key_len = htons (key_len);
790 GNUNET_CRYPTO_write_private_key_to_buffer (zone_key,
791 &zir_msg[1],
792 key_len);
793 zir_msg->expire = GNUNET_TIME_absolute_hton (block_exp);
794 name_tmp = (char *) &zir_msg[1] + key_len;
795 GNUNET_memcpy (name_tmp, name, name_len);
796 rd_ser = &name_tmp[name_len];
797 GNUNET_assert (
798 rd_ser_len ==
799 GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser));
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
801 "Sending RECORD_RESULT message with %u records\n",
802 res_count);
803 GNUNET_STATISTICS_update (statistics,
804 "Record sets sent to clients",
805 1,
806 GNUNET_NO);
807 GNUNET_MQ_send (nc->mq, env);
808 if (rd_nf != res)
809 GNUNET_free (res);
810 return res_count;
811}
812
813/**
814 * Send response to the store request to the client.
815 *
816 * @param nc client to talk to
817 * @param ec status of the operation
818 * @param rid client's request ID
819 */
820static void
821send_store_response (struct NamestoreClient *nc,
822 enum GNUNET_ErrorCode ec,
823 uint32_t rid)
824{
825 struct GNUNET_MQ_Envelope *env;
826 struct RecordStoreResponseMessage *rcr_msg;
827
828 GNUNET_assert (NULL != nc);
829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
830 "Sending RECORD_STORE_RESPONSE message\n");
831 GNUNET_STATISTICS_update (statistics,
832 "Store requests completed",
833 1,
834 GNUNET_NO);
835 env = GNUNET_MQ_msg (rcr_msg,
836 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
837 rcr_msg->gns_header.r_id = htonl (rid);
838 rcr_msg->ec = htonl (ec);
839 GNUNET_MQ_send (nc->mq, env);
840}
841
842
843/**
844 * Function called once we are done with the zone iteration and
845 * allow the zone iteration client to send us more messages.
846 *
847 * @param zi zone iteration we are processing
848 */
849static void
850zone_iteration_done_client_continue (struct ZoneIteration *zi)
851{
852 struct GNUNET_MQ_Envelope *env;
853 struct GNUNET_NAMESTORE_Header *em;
854
855 GNUNET_SERVICE_client_continue (zi->nc->client);
856 if (! zi->send_end)
857 return;
858 /* send empty response to indicate end of list */
859 env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
860 em->r_id = htonl (zi->request_id);
861 GNUNET_MQ_send (zi->nc->mq, env);
862
863 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi);
864 GNUNET_free (zi);
865}
866
867
868
869
870/**
871 * Print a warning that one of our monitors is no longer reacting.
872 *
873 * @param cls a `struct ZoneMonitor` to warn about
874 */
875static void
876warn_monitor_slow (void *cls)
877{
878 struct ZoneMonitor *zm = cls;
879
880 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
881 "No response from monitor since %s\n",
882 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
883 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
884 &warn_monitor_slow,
885 zm);
886}
887
888
889/**
890 * Continue processing the @a sa.
891 *
892 * @param sa store activity to process
893 */
894static int
895continue_store_activity (struct StoreActivity *sa,
896 int call_continue)
897{
898 const struct RecordSet *rd_set = sa->rs;
899 unsigned int rd_count;
900 size_t name_len;
901 size_t rd_ser_len;
902 const char *name_tmp;
903 const char *rd_ser;
904 const char *buf;
905 char *conv_name;
906
907 // If we are in a transaction, do not notify monitors or update
908 // cached. This will be done when we are commiting.
909 if (GNUNET_YES == sa->uncommited)
910 {
911 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
912 "Transaction not yet committed, delaying monitor and cache updates\n");
913 send_store_response (sa->nc, GNUNET_EC_NONE, sa->rid);
914 if (GNUNET_YES == call_continue)
915 GNUNET_SERVICE_client_continue (sa->nc->client);
916 return GNUNET_OK;
917 }
918 buf = (const char *) &sa[1];
919 for (int i = sa->rd_set_pos; i < sa->rd_set_count; i++)
920 {
921 rd_set = (struct RecordSet *) buf;
922 name_len = ntohs (rd_set->name_len);
923 rd_count = ntohs (rd_set->rd_count);
924 rd_ser_len = ntohs (rd_set->rd_len);
925 name_tmp = (const char *) &rd_set[1];
926 rd_ser = &name_tmp[name_len];
927 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
928 GNUNET_assert (NULL != conv_name);
929 {
930 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
931
932 /* We did this before, must succeed again */
933 GNUNET_assert (
934 GNUNET_OK ==
935 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count,
936 rd));
937
938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
939 "Checking monitors watching for `%s'\n",
940 conv_name);
941 for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos)
942 {
943 if ((0 != GNUNET_memcmp (&sa->private_key, &zm->zone)) &&
944 (0 != GNUNET_memcmp (&zm->zone, &zero)))
945 {
946 sa->zm_pos = zm->next; /* not interesting to this monitor */
947 continue;
948 }
949 if (zm->limit == zm->iteration_cnt)
950 {
951 zm->sa_waiting = GNUNET_YES;
952 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
953 if (NULL != zm->sa_wait_warning)
954 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
955 zm->sa_wait_warning =
956 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
957 &warn_monitor_slow,
958 zm);
959 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
960 "Monitor is blocking client for `%s'\n",
961 conv_name);
962 GNUNET_free (conv_name);
963 return GNUNET_NO; /* blocked on zone monitor */
964 }
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
966 "Notifying monitor about changes under label `%s'\n",
967 conv_name);
968 if (0 < send_lookup_response_with_filter (zm->nc,
969 0,
970 &sa->private_key,
971 conv_name,
972 rd_count,
973 rd,
974 zm->filter))
975 zm->limit--;
976 sa->zm_pos = zm->next;
977 }
978 sa->rd_set_pos++;
979 GNUNET_free (conv_name);
980 }
981 }
982 if (GNUNET_YES == call_continue)
983 GNUNET_SERVICE_client_continue (sa->nc->client);
984 send_store_response (sa->nc, GNUNET_EC_NONE, sa->rid);
985 free_store_activity (sa);
986 return GNUNET_OK;
987}
988
989
990/**
991 * Called whenever a client is disconnected.
992 * Frees our resources associated with that client.
993 *
994 * @param cls closure
995 * @param client identification of the client
996 * @param app_ctx the `struct NamestoreClient` of @a client
997 */
998static void
999client_disconnect_cb (void *cls,
1000 struct GNUNET_SERVICE_Client *client,
1001 void *app_ctx)
1002{
1003 struct NamestoreClient *nc = app_ctx;
1004 struct ZoneIteration *no;
1005 struct StoreActivity *sa = sa_head;
1006 struct StoreActivity *sn;
1007 char *emsg;
1008
1009 (void) cls;
1010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1011 if (GNUNET_YES == nc->in_transaction)
1012 {
1013 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1014 "Client in transaction, rolling back...\n");
1015 if (GNUNET_SYSERR == nc->GSN_database->transaction_rollback (
1016 nc->GSN_database->cls,
1017 &emsg))
1018 {
1019 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1020 "Unable to roll back: %s\n", emsg);
1021 GNUNET_free (emsg);
1022 }
1023 else
1024 {
1025 nc->in_transaction = GNUNET_NO;
1026 while (NULL != sa)
1027 {
1028 if ((nc != sa->nc) ||
1029 (GNUNET_NO == sa->uncommited))
1030 {
1031 sa = sa->next;
1032 continue;
1033 }
1034 sn = sa->next;
1035 free_store_activity (sa);
1036 sa = sn;
1037 }
1038 }
1039 }
1040 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1041 {
1042 if (nc != zm->nc)
1043 continue;
1044 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm);
1045 if (NULL != zm->task)
1046 {
1047 GNUNET_SCHEDULER_cancel (zm->task);
1048 zm->task = NULL;
1049 }
1050 if (NULL != zm->sa_wait_warning)
1051 {
1052 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1053 zm->sa_wait_warning = NULL;
1054 }
1055 for (sa = sa_head; NULL != sa; sa = sn)
1056 {
1057 sn = sa->next;
1058 if (zm == sa->zm_pos)
1059 {
1060 sa->zm_pos = zm->next;
1061 /* this may free sa */
1062 continue_store_activity (sa, GNUNET_YES);
1063 }
1064 }
1065 GNUNET_free (zm);
1066 break;
1067 }
1068 sa = sa_head;
1069 while (NULL != sa)
1070 {
1071 if (nc != sa->nc)
1072 {
1073 sa = sa->next;
1074 continue;
1075 }
1076 sn = sa->next;
1077 free_store_activity (sa);
1078 sa = sn;
1079 }
1080 while (NULL != (no = nc->op_head))
1081 {
1082 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
1083 GNUNET_free (no);
1084 }
1085 GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name,
1086 nc->GSN_database));
1087 GNUNET_free (nc->db_lib_name);
1088 GNUNET_free (nc);
1089}
1090
1091
1092/**
1093 * Add a client to our list of active clients.
1094 *
1095 * @param cls NULL
1096 * @param client client to add
1097 * @param mq message queue for @a client
1098 * @return internal namestore client structure for this client
1099 */
1100static void *
1101client_connect_cb (void *cls,
1102 struct GNUNET_SERVICE_Client *client,
1103 struct GNUNET_MQ_Handle *mq)
1104{
1105 struct NamestoreClient *nc;
1106 char *database;
1107
1108 (void) cls;
1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1110 nc = GNUNET_new (struct NamestoreClient);
1111 nc->client = client;
1112 nc->mq = mq;
1113 /* Loading database plugin */
1114 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (GSN_cfg,
1115 "namestore",
1116 "database",
1117 &database))
1118 {
1119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1120 GNUNET_free (nc);
1121 return NULL;
1122 }
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
1124 nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1125 GNUNET_free (database);
1126 if (NULL == nc->GSN_database)
1127 {
1128 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1129 "Could not load database backend `%s'\n",
1130 db_lib_name);
1131 GNUNET_free (nc);
1132 return NULL;
1133 }
1134 nc->db_lib_name = GNUNET_strdup (db_lib_name);
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded %s\n", db_lib_name);
1136 return nc;
1137}
1138
1139
1140/**
1141 * Closure for #lookup_it().
1142 */
1143struct RecordLookupContext
1144{
1145 /**
1146 * The label to look up.
1147 */
1148 const char *label;
1149
1150 /**
1151 * The record result.
1152 */
1153 char *res_rd;
1154
1155 /**
1156 * The nick for the zone.
1157 */
1158 struct GNUNET_GNSRECORD_Data *nick;
1159
1160 /**
1161 * If a record set was found or not.
1162 */
1163 int found;
1164
1165 /**
1166 * The record filter
1167 */
1168 enum GNUNET_GNSRECORD_Filter filter;
1169
1170 /**
1171 * The number of found records.
1172 */
1173 unsigned int res_rd_count;
1174
1175 /**
1176 * The length of the serialized records.
1177 */
1178 ssize_t rd_ser_len;
1179};
1180
1181
1182/**
1183 * Function called by the namestore plugin when we are trying to lookup
1184 * a record as part of #handle_record_lookup(). Merges all results into
1185 * the context.
1186 *
1187 * @param cls closure with a `struct RecordLookupContext`
1188 * @param seq unique serial number of the record, MUST NOT BE ZERO
1189 * @param private_key private key of the zone
1190 * @param label name that is being mapped (at most 255 characters long)
1191 * @param rd_count number of entries in @a rd array
1192 * @param rd array of records with data to store
1193 */
1194static void
1195lookup_it (void *cls,
1196 uint64_t seq,
1197 const struct GNUNET_CRYPTO_PrivateKey *private_key,
1198 const char *label,
1199 unsigned int rd_count_nf,
1200 const struct GNUNET_GNSRECORD_Data *rd_nf)
1201{
1202 struct RecordLookupContext *rlc = cls;
1203 struct GNUNET_GNSRECORD_Data rd[rd_count_nf];
1204 struct GNUNET_TIME_Absolute block_exp;
1205 unsigned int rd_count = 0;
1206 char *emsg;
1207
1208 (void) private_key;
1209 GNUNET_assert (0 != seq);
1210 if (0 != strcmp (label, rlc->label))
1211 return;
1212 rlc->found = GNUNET_YES;
1213
1214 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (rlc->label,
1215 rd_nf,
1216 rd_count_nf,
1217 rd,
1218 &rd_count,
1219 &block_exp,
1220 rlc->filter,
1221 &emsg))
1222 {
1223 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
1224 GNUNET_free (emsg);
1225 GNUNET_assert (0);
1226 }
1227
1228 if (0 == rd_count)
1229 {
1230 rlc->rd_ser_len = 0;
1231 rlc->res_rd_count = 0;
1232 rlc->res_rd = NULL;
1233 return;
1234 }
1235 if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)))
1236 {
1237 /* Merge */
1238 struct GNUNET_GNSRECORD_Data *rd_res;
1239 unsigned int rdc_res;
1240
1241 rd_res = NULL;
1242 rdc_res = 0;
1243 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE)
1244 ^ GNUNET_GNSRECORD_RF_PRIVATE;
1245 merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res);
1246 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res);
1247 if (rlc->rd_ser_len < 0)
1248 {
1249 GNUNET_break (0);
1250 GNUNET_free (rd_res);
1251 rlc->found = GNUNET_NO;
1252 rlc->rd_ser_len = 0;
1253 return;
1254 }
1255 rlc->res_rd_count = rdc_res;
1256 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1257 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res,
1258 rd_res,
1259 rlc->rd_ser_len,
1260 rlc->res_rd))
1261 {
1262 GNUNET_break (0);
1263 GNUNET_free (rlc->res_rd);
1264 rlc->res_rd = NULL;
1265 rlc->res_rd_count = 0;
1266 rlc->rd_ser_len = 0;
1267 GNUNET_free (rd_res);
1268 rlc->found = GNUNET_NO;
1269 return;
1270 }
1271 GNUNET_free (rd_res);
1272 GNUNET_free (rlc->nick);
1273 rlc->nick = NULL;
1274 }
1275 else
1276 {
1277 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1278 if (rlc->rd_ser_len < 0)
1279 {
1280 GNUNET_break (0);
1281 rlc->found = GNUNET_NO;
1282 rlc->rd_ser_len = 0;
1283 return;
1284 }
1285 rlc->res_rd_count = rd_count;
1286 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1287 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count,
1288 rd,
1289 rlc->rd_ser_len,
1290 rlc->res_rd))
1291 {
1292 GNUNET_break (0);
1293 GNUNET_free (rlc->res_rd);
1294 rlc->res_rd = NULL;
1295 rlc->res_rd_count = 0;
1296 rlc->rd_ser_len = 0;
1297 rlc->found = GNUNET_NO;
1298 return;
1299 }
1300 }
1301}
1302
1303
1304/**
1305 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1306 *
1307 * @param cls client sending the message
1308 * @param ll_msg message of type `struct LabelLookupMessage`
1309 * @return #GNUNET_OK if @a ll_msg is well-formed
1310 */
1311static int
1312check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1313{
1314 uint32_t name_len;
1315 size_t src_size;
1316 size_t key_len;
1317
1318 (void) cls;
1319 name_len = ntohs (ll_msg->label_len);
1320 key_len = ntohs (ll_msg->key_len);
1321 src_size = ntohs (ll_msg->gns_header.header.size);
1322 if (name_len + key_len != src_size - sizeof(struct LabelLookupMessage))
1323 {
1324 GNUNET_break (0);
1325 return GNUNET_SYSERR;
1326 }
1327 return GNUNET_OK;
1328}
1329
1330
1331/**
1332 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1333 *
1334 * @param cls client sending the message
1335 * @param ll_msg message of type `struct LabelLookupMessage`
1336 */
1337static void
1338handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1339{
1340 struct GNUNET_CRYPTO_PrivateKey zone;
1341 struct NamestoreClient *nc = cls;
1342 struct GNUNET_MQ_Envelope *env;
1343 struct LabelLookupResponseMessage *llr_msg;
1344 struct RecordLookupContext rlc;
1345 const char *name_tmp;
1346 char *res_name;
1347 char *conv_name;
1348 uint32_t name_len;
1349 int res;
1350 size_t key_len;
1351 size_t kb_read;
1352
1353 key_len = ntohs (ll_msg->key_len);
1354 if ((GNUNET_SYSERR ==
1355 GNUNET_CRYPTO_read_private_key_from_buffer (&ll_msg[1],
1356 key_len,
1357 &zone,
1358 &kb_read)) ||
1359 (kb_read != key_len))
1360 {
1361 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1362 "Error reading private key\n");
1363 GNUNET_SERVICE_client_drop (nc->client);
1364 return;
1365 }
1366 name_tmp = (const char *) &ll_msg[1] + key_len;
1367 GNUNET_SERVICE_client_continue (nc->client);
1368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1369 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1370 name_tmp);
1371
1372 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1373 if (NULL == conv_name)
1374 {
1375 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1376 "Error converting name `%s'\n",
1377 name_tmp);
1378 GNUNET_SERVICE_client_drop (nc->client);
1379 return;
1380 }
1381 name_len = strlen (conv_name) + 1;
1382 rlc.label = conv_name;
1383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1384 "Looking up with filter %u\n", ntohs (ll_msg->filter));
1385 rlc.filter = ntohs (ll_msg->filter);
1386 rlc.found = GNUNET_NO;
1387 rlc.res_rd_count = 0;
1388 rlc.res_rd = NULL;
1389 rlc.rd_ser_len = 0;
1390 rlc.nick = get_nick_record (&zone);
1391 if (GNUNET_YES != ntohs (ll_msg->is_edit_request))
1392 res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
1393 &zone,
1394 conv_name,
1395 &lookup_it,
1396 &rlc);
1397 else
1398 res = nc->GSN_database->edit_records (nc->GSN_database->cls,
1399 &zone,
1400 conv_name,
1401 &lookup_it,
1402 &rlc);
1403
1404 env =
1405 GNUNET_MQ_msg_extra (llr_msg,
1406 key_len + name_len + rlc.rd_ser_len,
1407 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1408 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1409 GNUNET_memcpy (&llr_msg[1], &ll_msg[1], key_len);
1410 llr_msg->key_len = ll_msg->key_len;
1411 llr_msg->name_len = htons (name_len);
1412 llr_msg->rd_count = htons (rlc.res_rd_count);
1413 llr_msg->rd_len = htons (rlc.rd_ser_len);
1414 llr_msg->reserved = htons (0);
1415 res_name = ((char *) &llr_msg[1]) + key_len;
1416 if (GNUNET_YES == rlc.found)
1417 llr_msg->found = htons (GNUNET_YES);
1418 else if (GNUNET_SYSERR == res)
1419 llr_msg->found = htons (GNUNET_SYSERR);
1420 else
1421 llr_msg->found = htons (GNUNET_NO);
1422 GNUNET_memcpy (res_name, conv_name, name_len);
1423 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1424 GNUNET_MQ_send (nc->mq, env);
1425 GNUNET_free (rlc.res_rd);
1426 GNUNET_free (conv_name);
1427}
1428
1429
1430
1431/**
1432 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1433 *
1434 * @param cls client sending the message
1435 * @param rp_msg message of type `struct RecordStoreMessage`
1436 * @return #GNUNET_OK if @a rp_msg is well-formed
1437 */
1438static int
1439check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1440{
1441 size_t msg_size;
1442 size_t min_size_exp;
1443 size_t rd_set_count;
1444 size_t key_len;
1445
1446 (void) cls;
1447 msg_size = ntohs (rp_msg->gns_header.header.size);
1448 rd_set_count = ntohs (rp_msg->rd_set_count);
1449 key_len = ntohs (rp_msg->key_len);
1450
1451 min_size_exp = sizeof(*rp_msg) + key_len + sizeof (struct RecordSet)
1452 * rd_set_count;
1453 if (msg_size < min_size_exp)
1454 {
1455 GNUNET_break (0);
1456 return GNUNET_SYSERR;
1457 }
1458 return GNUNET_OK;
1459}
1460
1461struct LookupExistingRecordsContext
1462{
1463
1464 /**
1465 * The expiration of the existing records or tombstone
1466 */
1467 struct GNUNET_TIME_Absolute exp;
1468
1469 /**
1470 * Whether the existing record set consists only of a tombstone
1471 * (e.g. is "empty")
1472 */
1473 int only_tombstone;
1474
1475};
1476
1477
1478/**
1479 * Check if set contains a tombstone, store if necessary
1480 *
1481 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
1482 * @param seq sequence number of the record, MUST NOT BE ZERO
1483 * @param private_key the private key of the zone (unused)
1484 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
1485 * @param rd_count number of records in @a rd
1486 * @param rd records stored under @a label in the zone
1487 */
1488static void
1489get_existing_rd_exp (void *cls,
1490 uint64_t seq,
1491 const struct
1492 GNUNET_CRYPTO_PrivateKey *private_key,
1493 const char *label,
1494 unsigned int rd_count,
1495 const struct GNUNET_GNSRECORD_Data *rd)
1496{
1497 struct LookupExistingRecordsContext *lctx = cls;
1498 struct GNUNET_GNSRECORD_Data rd_pub[rd_count];
1499 unsigned int rd_pub_count;
1500 char *emsg;
1501
1502 if ((1 == rd_count) &&
1503 (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[0].record_type))
1504 {
1505 /* This record set contains only a tombstone! */
1506 lctx->only_tombstone = GNUNET_YES;
1507 }
1508 if (GNUNET_OK !=
1509 GNUNET_GNSRECORD_normalize_record_set (label,
1510 rd,
1511 rd_count,
1512 rd_pub,
1513 &rd_pub_count,
1514 &lctx->exp,
1515 GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE,
1516 &emsg))
1517 {
1518 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1519 "%s\n", emsg);
1520 GNUNET_free (emsg);
1521 }
1522}
1523
1524static enum GNUNET_ErrorCode
1525store_record_set (struct NamestoreClient *nc,
1526 const struct GNUNET_CRYPTO_PrivateKey *private_key,
1527 const struct RecordSet *rd_set,
1528 ssize_t *len)
1529{
1530 size_t name_len;
1531 size_t rd_ser_len;
1532 const char *name_tmp;
1533 const char *rd_ser;
1534 char *conv_name;
1535 char *emsg;
1536 unsigned int rd_count;
1537 int res;
1538 enum GNUNET_ErrorCode ec;
1539 struct GNUNET_TIME_Absolute new_block_exp;
1540 struct LookupExistingRecordsContext lctx;
1541 *len = sizeof (struct RecordSet);
1542
1543 ec = GNUNET_EC_NONE;
1544 lctx.only_tombstone = GNUNET_NO;
1545 lctx.exp = GNUNET_TIME_UNIT_ZERO_ABS;
1546 new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1547 name_len = ntohs (rd_set->name_len);
1548 *len += name_len;
1549 rd_count = ntohs (rd_set->rd_count);
1550 rd_ser_len = ntohs (rd_set->rd_len);
1551 *len += rd_ser_len;
1552 name_tmp = (const char *) &rd_set[1];
1553 rd_ser = &name_tmp[name_len];
1554 {
1555 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1556
1557 /* Extracting and converting private key */
1558 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1559 if (NULL == conv_name)
1560 {
1561 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1562 "Error normalizing name `%s'\n",
1563 name_tmp);
1564 return GNUNET_EC_NAMESTORE_LABEL_INVALID;
1565 }
1566
1567 /* Check name for validity */
1568 if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg))
1569 {
1570 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1571 "Label invalid: `%s'\n",
1572 emsg);
1573 GNUNET_free (emsg);
1574 GNUNET_free (conv_name);
1575 return GNUNET_EC_NAMESTORE_LABEL_INVALID;
1576 }
1577
1578 if (GNUNET_OK !=
1579 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count,
1580 rd))
1581 {
1582 GNUNET_free (conv_name);
1583 return GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID;
1584 }
1585
1586 GNUNET_STATISTICS_update (statistics,
1587 "Well-formed store requests received",
1588 1,
1589 GNUNET_NO);
1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1591 "Creating %u records for name `%s'\n",
1592 (unsigned int) rd_count,
1593 conv_name);
1594 if ((GNUNET_NO == nc->GSN_database->lookup_records (nc->GSN_database->cls,
1595 private_key,
1596 conv_name,
1597 &get_existing_rd_exp,
1598 &lctx))
1599 &&
1600 (rd_count == 0))
1601 {
1602 /* This name does not exist, so cannot be removed */
1603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1604 "Name `%s' does not exist, no deletion required\n",
1605 conv_name);
1606 res = GNUNET_NO;
1607 ec = GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND;
1608 }
1609 else
1610 {
1611 /* remove "NICK" records, unless this is for the
1612 #GNUNET_GNS_EMPTY_LABEL_AT label
1613 We may need one additional record later for tombstone.
1614 FIXME: Since we must normalize the record set (check for
1615 consistency etc) we have to iterate the set twice.
1616 May be inefficient.
1617 We cannot really move the nick caching into GNSRECORD.
1618 */
1619 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1620 struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1];
1621 unsigned int rd_clean_off;
1622 unsigned int rd_nf_count;
1623 int have_nick;
1624
1625 rd_clean_off = 0;
1626 have_nick = GNUNET_NO;
1627 for (unsigned int i = 0; i < rd_count; i++)
1628 {
1629 rd_clean[rd_clean_off] = rd[i];
1630
1631 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1632 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1633 rd_clean_off++;
1634
1635 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1636 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
1637 {
1638 // FIXME: In case this is an uncommited transaction,
1639 // we should not do this here. Can we do this in the store activity?
1640 cache_nick (private_key, &rd[i]);
1641 have_nick = GNUNET_YES;
1642 }
1643 }
1644 if (GNUNET_OK !=
1645 GNUNET_GNSRECORD_normalize_record_set (conv_name,
1646 rd_clean,
1647 rd_clean_off,
1648 rd_nf,
1649 &rd_nf_count,
1650 &new_block_exp,
1651 GNUNET_GNSRECORD_FILTER_NONE,
1652 &emsg))
1653 {
1654 GNUNET_free (conv_name);
1655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1656 "Error normalizing record set: `%s'\n",
1657 emsg);
1658 GNUNET_free (emsg);
1659 return GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID;
1660 }
1661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1662 "%u/%u records before tombstone\n", rd_nf_count,
1663 rd_clean_off);
1664 /*
1665 * If existing_block_exp is 0, then there was no record set
1666 * and no tombstone.
1667 * Otherwise, if the existing block expiration is after the
1668 * new block expiration would be, we need to add a tombstone
1669 * or update it.
1670 */
1671 if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, lctx.exp))
1672 {
1673 rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
1674 rd_nf[rd_nf_count].expiration_time =
1675 lctx.exp.abs_value_us;
1676 rd_nf[rd_nf_count].data = NULL;
1677 rd_nf[rd_nf_count].data_size = 0;
1678 rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1679 rd_nf_count++;
1680 }
1681 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1682 (GNUNET_NO == have_nick))
1683 {
1684 /* remove nick record from cache, in case we have one there */
1685 // FIXME: In case this is an uncommited transaction,
1686 // we should not do this here. Can we do this in the store activity?
1687 cache_nick (private_key, NULL);
1688 }
1689 res = nc->GSN_database->store_records (nc->GSN_database->cls,
1690 private_key,
1691 conv_name,
1692 rd_nf_count,
1693 rd_nf);
1694 /* If after a store there is only a TOMBSTONE left, and
1695 * there was >1 record under this label found (the tombstone; indicated
1696 * through res != GNUNET_NO) then we should return "NOT FOUND" == GNUNET_NO
1697 */
1698 if ((GNUNET_SYSERR != res) &&
1699 (0 == rd_count) &&
1700 (1 == rd_nf_count) &&
1701 (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd_nf[0].record_type) &&
1702 (GNUNET_YES == lctx.only_tombstone))
1703 {
1704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1705 "Client tried to remove non-existant record\n");
1706 ec = GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND;
1707 }
1708 }
1709
1710 if (GNUNET_SYSERR == res)
1711 {
1712 /* store not successful, no need to tell monitors */
1713 GNUNET_free (conv_name);
1714 return GNUNET_EC_NAMESTORE_STORE_FAILED;
1715 }
1716 }
1717 GNUNET_free (conv_name);
1718 return ec;
1719}
1720
1721/**
1722 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1723 *
1724 * @param cls client sending the message
1725 * @param rp_msg message of type `struct RecordStoreMessage`
1726 */
1727static void
1728handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1729{
1730 struct GNUNET_CRYPTO_PrivateKey zone;
1731 struct NamestoreClient *nc = cls;
1732 uint32_t rid;
1733 uint16_t rd_set_count;
1734 const char *buf;
1735 ssize_t read;
1736 size_t key_len;
1737 size_t kb_read;
1738 size_t rp_msg_len;
1739 size_t rs_len;
1740 size_t rs_off;
1741 struct StoreActivity *sa;
1742 struct RecordSet *rs;
1743 enum GNUNET_ErrorCode res;
1744
1745 key_len = ntohs (rp_msg->key_len);
1746 rp_msg_len = ntohs (rp_msg->gns_header.header.size);
1747 rs_off = sizeof (*rp_msg) + key_len;
1748 rs_len = rp_msg_len - rs_off;
1749 if ((GNUNET_SYSERR ==
1750 GNUNET_CRYPTO_read_private_key_from_buffer (&rp_msg[1],
1751 key_len,
1752 &zone,
1753 &kb_read)) ||
1754 (kb_read != key_len))
1755 {
1756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1757 "Error reading private key\n");
1758 GNUNET_SERVICE_client_drop (nc->client);
1759 return;
1760 }
1761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1762 "Received NAMESTORE_RECORD_STORE message\n");
1763 rid = ntohl (rp_msg->gns_header.r_id);
1764 rd_set_count = ntohs (rp_msg->rd_set_count);
1765 buf = (const char *) rp_msg + rs_off;
1766 for (int i = 0; i < rd_set_count; i++)
1767 {
1768 rs = (struct RecordSet *) buf;
1769 res = store_record_set (nc, &zone,
1770 rs, &read);
1771 if (GNUNET_EC_NONE != res)
1772 {
1773 send_store_response (nc, res, rid);
1774 GNUNET_SERVICE_client_continue (nc->client);
1775 return;
1776 }
1777 buf += read;
1778 }
1779 sa = GNUNET_malloc (sizeof(struct StoreActivity) + rs_len);
1780 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1781 sa->nc = nc;
1782 sa->rs = (struct RecordSet *) &sa[1];
1783 sa->rd_set_count = rd_set_count;
1784 GNUNET_memcpy (&sa[1], (char *) rp_msg + rs_off, rs_len);
1785 sa->rid = rid;
1786 sa->rd_set_pos = 0;
1787 sa->private_key = zone;
1788 sa->zm_pos = monitor_head;
1789 sa->uncommited = nc->in_transaction;
1790 continue_store_activity (sa, GNUNET_YES);
1791}
1792
1793static void
1794send_tx_response (int rid, enum GNUNET_ErrorCode ec, struct NamestoreClient *nc)
1795{
1796 struct TxControlResultMessage *txr_msg;
1797 struct GNUNET_MQ_Envelope *env;
1798
1799 env =
1800 GNUNET_MQ_msg (txr_msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT);
1801 txr_msg->gns_header.r_id = rid;
1802 txr_msg->ec = htonl (ec);
1803 GNUNET_MQ_send (nc->mq, env);
1804}
1805
1806/**
1807 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL message
1808 *
1809 * @param cls client sending the message
1810 * @param tx_msg message of type `struct TxControlMessage`
1811 */
1812static void
1813handle_tx_control (void *cls, const struct TxControlMessage *tx_msg)
1814{
1815 struct NamestoreClient *nc = cls;
1816 struct StoreActivity *sa = sa_head;
1817 struct StoreActivity *sn;
1818 enum GNUNET_GenericReturnValue ret;
1819 char *emsg = NULL;
1820 int blocked = GNUNET_NO;
1821
1822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received TX_CONTROL message\n");
1823
1824 switch (ntohs (tx_msg->control))
1825 {
1826 case GNUNET_NAMESTORE_TX_BEGIN:
1827 ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls,
1828 &emsg);
1829 send_tx_response (tx_msg->gns_header.r_id,
1830 (GNUNET_SYSERR == ret) ?
1831 GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, nc);
1832 if (GNUNET_SYSERR == ret)
1833 {
1834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1835 "Databse backend error: `%s'", emsg);
1836 GNUNET_free (emsg);
1837 }
1838 GNUNET_SERVICE_client_continue (nc->client);
1839 nc->in_transaction = GNUNET_YES;
1840 break;
1841 case GNUNET_NAMESTORE_TX_COMMIT:
1842 ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls,
1843 &emsg);
1844 send_tx_response (tx_msg->gns_header.r_id,
1845 (GNUNET_SYSERR == ret) ?
1846 GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE,
1847 nc);
1848 if (GNUNET_SYSERR == ret)
1849 {
1850 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1851 "Databse backend error: `%s'", emsg);
1852 GNUNET_free (emsg);
1853 }
1854 if (GNUNET_SYSERR != ret)
1855 {
1856 nc->in_transaction = GNUNET_NO;
1857 while (NULL != sa)
1858 {
1859 if ((nc != sa->nc) ||
1860 (GNUNET_NO == sa->uncommited))
1861 {
1862 sa = sa->next;
1863 continue;
1864 }
1865 sa->uncommited = GNUNET_NO;
1866 sn = sa->next;
1867 if (GNUNET_OK != continue_store_activity (sa, GNUNET_NO))
1868 blocked = GNUNET_YES;
1869 sa = sn;
1870 }
1871 if (GNUNET_YES != blocked)
1872 GNUNET_SERVICE_client_continue (nc->client);
1873 }
1874 break;
1875 case GNUNET_NAMESTORE_TX_ROLLBACK:
1876 ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls,
1877 &emsg);
1878 send_tx_response (tx_msg->gns_header.r_id,
1879 (GNUNET_SYSERR == ret) ?
1880 GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, nc);
1881 GNUNET_SERVICE_client_continue (nc->client);
1882 if (GNUNET_SYSERR == ret)
1883 {
1884 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1885 "Databse backend error: `%s'", emsg);
1886 GNUNET_free (emsg);
1887 }
1888 if (GNUNET_SYSERR != ret)
1889 {
1890 nc->in_transaction = GNUNET_NO;
1891 while (NULL != sa)
1892 {
1893 if ((nc != sa->nc) ||
1894 (GNUNET_NO == sa->uncommited))
1895 {
1896 sa = sa->next;
1897 continue;
1898 }
1899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1900 "Discarding uncommited StoreActivity\n");
1901 sn = sa->next;
1902 free_store_activity (sa);
1903 sa = sn;
1904 }
1905 }
1906 break;
1907 default:
1908 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1909 "Unknown control type %u\n", ntohs (tx_msg->control));
1910 GNUNET_break (0);
1911 }
1912}
1913
1914/**
1915 * Context for record remove operations passed from #handle_zone_to_name to
1916 * #handle_zone_to_name_it as closure
1917 */
1918struct ZoneToNameCtx
1919{
1920 /**
1921 * Namestore client
1922 */
1923 struct NamestoreClient *nc;
1924
1925 /**
1926 * Request id (to be used in the response to the client).
1927 */
1928 uint32_t rid;
1929
1930 /**
1931 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1932 * not finding a name for the zone still counts as a 'success' here,
1933 * as this field is about the success of executing the IPC protocol.
1934 */
1935 enum GNUNET_ErrorCode ec;
1936};
1937
1938
1939/**
1940 * Zone to name iterator
1941 *
1942 * @param cls struct ZoneToNameCtx *
1943 * @param seq sequence number of the record, MUST NOT BE ZERO
1944 * @param zone_key the zone key
1945 * @param name name
1946 * @param rd_count number of records in @a rd
1947 * @param rd record data
1948 */
1949static void
1950handle_zone_to_name_it (void *cls,
1951 uint64_t seq,
1952 const struct GNUNET_CRYPTO_PrivateKey *zone_key,
1953 const char *name,
1954 unsigned int rd_count,
1955 const struct GNUNET_GNSRECORD_Data *rd)
1956{
1957 struct ZoneToNameCtx *ztn_ctx = cls;
1958 struct GNUNET_MQ_Envelope *env;
1959 struct ZoneToNameResponseMessage *ztnr_msg;
1960 size_t name_len;
1961 size_t key_len;
1962 ssize_t rd_ser_len;
1963 size_t msg_size;
1964 char *name_tmp;
1965 char *rd_tmp;
1966
1967 GNUNET_assert (0 != seq);
1968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1969 "Found result for zone-to-name lookup: `%s'\n",
1970 name);
1971 ztn_ctx->ec = GNUNET_EC_NONE;
1972 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1973 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1974 if (rd_ser_len < 0)
1975 {
1976 GNUNET_break (0);
1977 ztn_ctx->ec = htonl (GNUNET_EC_NAMESTORE_UNKNOWN);
1978 return;
1979 }
1980 key_len = GNUNET_CRYPTO_private_key_get_length (zone_key);
1981 msg_size = sizeof(struct ZoneToNameResponseMessage)
1982 + name_len + rd_ser_len + key_len;
1983 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1984 {
1985 GNUNET_break (0);
1986 ztn_ctx->ec = GNUNET_EC_NAMESTORE_RECORD_TOO_BIG;
1987 return;
1988 }
1989 env =
1990 GNUNET_MQ_msg_extra (ztnr_msg,
1991 key_len + name_len + rd_ser_len,
1992 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1993 ztnr_msg->gns_header.header.size = htons (msg_size);
1994 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1995 ztnr_msg->ec = htonl (ztn_ctx->ec);
1996 ztnr_msg->rd_len = htons (rd_ser_len);
1997 ztnr_msg->rd_count = htons (rd_count);
1998 ztnr_msg->name_len = htons (name_len);
1999 ztnr_msg->key_len = htons (key_len);
2000 GNUNET_CRYPTO_write_private_key_to_buffer (zone_key,
2001 &ztnr_msg[1],
2002 key_len);
2003 name_tmp = (char *) &ztnr_msg[1] + key_len;
2004 GNUNET_memcpy (name_tmp, name, name_len);
2005 rd_tmp = &name_tmp[name_len];
2006 GNUNET_assert (
2007 rd_ser_len ==
2008 GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
2009 ztn_ctx->ec = GNUNET_EC_NONE;
2010 GNUNET_MQ_send (ztn_ctx->nc->mq, env);
2011}
2012
2013static enum GNUNET_GenericReturnValue
2014check_zone_to_name (void *cls,
2015 const struct ZoneToNameMessage *zis_msg)
2016{
2017 return GNUNET_OK;
2018}
2019
2020
2021/**
2022 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
2023 *
2024 * @param cls client client sending the message
2025 * @param ztn_msg message of type 'struct ZoneToNameMessage'
2026 */
2027static void
2028handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
2029{
2030 struct GNUNET_CRYPTO_PrivateKey zone;
2031 struct GNUNET_CRYPTO_PublicKey value_zone;
2032 struct NamestoreClient *nc = cls;
2033 struct ZoneToNameCtx ztn_ctx;
2034 struct GNUNET_MQ_Envelope *env;
2035 struct ZoneToNameResponseMessage *ztnr_msg;
2036 size_t key_len;
2037 size_t pkey_len;
2038 size_t kb_read;
2039
2040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
2041 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
2042 ztn_ctx.nc = nc;
2043 ztn_ctx.ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND;
2044 key_len = ntohs (ztn_msg->key_len);
2045 if ((GNUNET_SYSERR ==
2046 GNUNET_CRYPTO_read_private_key_from_buffer (&ztn_msg[1],
2047 key_len,
2048 &zone,
2049 &kb_read)) ||
2050 (kb_read != key_len))
2051 {
2052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2053 "Error parsing private key.\n");
2054 GNUNET_SERVICE_client_drop (nc->client);
2055 GNUNET_break (0);
2056 return;
2057 }
2058 pkey_len = ntohs (ztn_msg->pkey_len);
2059 if ((GNUNET_SYSERR ==
2060 GNUNET_CRYPTO_read_public_key_from_buffer ((char*) &ztn_msg[1]
2061 + key_len,
2062 pkey_len,
2063 &value_zone,
2064 &kb_read)) ||
2065 (kb_read != pkey_len))
2066 {
2067 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2068 "Error parsing public key.\n");
2069 GNUNET_SERVICE_client_drop (nc->client);
2070 GNUNET_break (0);
2071 return;
2072 }
2073 if (GNUNET_SYSERR == nc->GSN_database->zone_to_name (nc->GSN_database->cls,
2074 &zone,
2075 &value_zone,
2076 &handle_zone_to_name_it,
2077 &ztn_ctx))
2078 {
2079 /* internal error, hang up instead of signalling something
2080 that might be wrong */
2081 GNUNET_break (0);
2082 GNUNET_SERVICE_client_drop (nc->client);
2083 return;
2084 }
2085 if (GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND == ztn_ctx.ec)
2086 {
2087 /* no result found, send empty response */
2088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2089 "Found no result for zone-to-name lookup.\n");
2090 env = GNUNET_MQ_msg (ztnr_msg,
2091 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
2092 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
2093 ztnr_msg->ec = htonl (GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND);
2094 GNUNET_MQ_send (nc->mq, env);
2095 }
2096 GNUNET_SERVICE_client_continue (nc->client);
2097}
2098
2099
2100/**
2101 * Context for record remove operations passed from
2102 * #run_zone_iteration_round to #zone_iterate_proc as closure
2103 */
2104struct ZoneIterationProcResult
2105{
2106 /**
2107 * The zone iteration handle
2108 */
2109 struct ZoneIteration *zi;
2110
2111 /**
2112 * Number of results left to be returned in this iteration.
2113 */
2114 uint64_t limit;
2115
2116 /**
2117 * Skip a result and run again unless GNUNET_NO
2118 */
2119 int run_again;
2120};
2121
2122
2123/**
2124 * Process results for zone iteration from database
2125 *
2126 * @param cls struct ZoneIterationProcResult
2127 * @param seq sequence number of the record, MUST NOT BE ZERO
2128 * @param zone_key the zone key
2129 * @param name name
2130 * @param rd_count number of records for this name
2131 * @param rd record data
2132 */
2133static void
2134zone_iterate_proc (void *cls,
2135 uint64_t seq,
2136 const struct GNUNET_CRYPTO_PrivateKey *zone_key,
2137 const char *name,
2138 unsigned int rd_count,
2139 const struct GNUNET_GNSRECORD_Data *rd)
2140{
2141 struct ZoneIterationProcResult *proc = cls;
2142
2143 GNUNET_assert (0 != seq);
2144 if ((NULL == zone_key) && (NULL == name))
2145 {
2146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
2147 return;
2148 }
2149 if ((NULL == zone_key) || (NULL == name))
2150 {
2151 /* what is this!? should never happen */
2152 GNUNET_break (0);
2153 return;
2154 }
2155 if (0 == proc->limit)
2156 {
2157 /* what is this!? should never happen */
2158 GNUNET_break (0);
2159 return;
2160 }
2161 proc->zi->seq = seq;
2162 if (0 < send_lookup_response_with_filter (proc->zi->nc,
2163 proc->zi->request_id,
2164 zone_key,
2165 name,
2166 rd_count,
2167 rd,
2168 proc->zi->filter))
2169 proc->limit--;
2170 else
2171 proc->run_again = GNUNET_YES;
2172}
2173
2174
2175/**
2176 * Perform the next round of the zone iteration.
2177 *
2178 * @param zi zone iterator to process
2179 * @param limit number of results to return in one pass
2180 */
2181static void
2182run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
2183{
2184 struct ZoneIterationProcResult proc;
2185 struct GNUNET_TIME_Absolute start;
2186 struct GNUNET_TIME_Relative duration;
2187 struct NamestoreClient *nc = zi->nc;
2188
2189 memset (&proc, 0, sizeof(proc));
2190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2191 "Asked to return up to %llu records at position %llu\n",
2192 (unsigned long long) limit,
2193 (unsigned long long) zi->seq);
2194 proc.zi = zi;
2195 proc.limit = limit;
2196 proc.run_again = GNUNET_YES;
2197 start = GNUNET_TIME_absolute_get ();
2198 while (GNUNET_YES == proc.run_again)
2199 {
2200 proc.run_again = GNUNET_NO;
2201 GNUNET_break (GNUNET_SYSERR !=
2202 nc->GSN_database->iterate_records (nc->GSN_database->cls,
2203 (GNUNET_YES ==
2204 GNUNET_is_zero (
2205 &zi->zone))
2206 ? NULL
2207 : &zi->zone,
2208 zi->seq,
2209 proc.limit,
2210 &zone_iterate_proc,
2211 &proc));
2212 }
2213 duration = GNUNET_TIME_absolute_get_duration (start);
2214 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
2215 GNUNET_STATISTICS_set (statistics,
2216 "NAMESTORE iteration delay (μs/record)",
2217 duration.rel_value_us,
2218 GNUNET_NO);
2219 if (0 == proc.limit)
2220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2221 "Returned %llu results, more results available\n",
2222 (unsigned long long) limit);
2223 zi->send_end = (0 != proc.limit);
2224 if (0 == zi->cache_ops)
2225 zone_iteration_done_client_continue (zi);
2226}
2227
2228static enum GNUNET_GenericReturnValue
2229check_iteration_start (void *cls,
2230 const struct ZoneIterationStartMessage *zis_msg)
2231{
2232 uint16_t size;
2233 size_t key_len;
2234
2235 size = ntohs (zis_msg->gns_header.header.size);
2236 key_len = ntohs (zis_msg->key_len);
2237
2238 if (size < key_len + sizeof(*zis_msg))
2239 {
2240 GNUNET_break (0);
2241 return GNUNET_SYSERR;
2242 }
2243 return GNUNET_OK;
2244}
2245
2246
2247/**
2248 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
2249 *
2250 * @param cls the client sending the message
2251 * @param zis_msg message from the client
2252 */
2253static void
2254handle_iteration_start (void *cls,
2255 const struct ZoneIterationStartMessage *zis_msg)
2256{
2257 struct GNUNET_CRYPTO_PrivateKey zone;
2258 struct NamestoreClient *nc = cls;
2259 struct ZoneIteration *zi;
2260 size_t key_len;
2261 size_t kb_read;
2262
2263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2264 "Received ZONE_ITERATION_START message\n");
2265 key_len = ntohs (zis_msg->key_len);
2266 zi = GNUNET_new (struct ZoneIteration);
2267 if (0 < key_len)
2268 {
2269 if ((GNUNET_SYSERR ==
2270 GNUNET_CRYPTO_read_private_key_from_buffer (&zis_msg[1],
2271 key_len,
2272 &zone,
2273 &kb_read)) ||
2274 (kb_read != key_len))
2275 {
2276 GNUNET_SERVICE_client_drop (nc->client);
2277 GNUNET_free (zi);
2278 return;
2279 }
2280 zi->zone = zone;
2281 }
2282 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2283 zi->filter = ntohs (zis_msg->filter);
2284 zi->offset = 0;
2285 zi->nc = nc;
2286 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2287 run_zone_iteration_round (zi, 1);
2288}
2289
2290
2291/**
2292 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
2293 *
2294 * @param cls the client sending the message
2295 * @param zis_msg message from the client
2296 */
2297static void
2298handle_iteration_stop (void *cls,
2299 const struct ZoneIterationStopMessage *zis_msg)
2300{
2301 struct NamestoreClient *nc = cls;
2302 struct ZoneIteration *zi;
2303 uint32_t rid;
2304
2305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2306 "Received ZONE_ITERATION_STOP message\n");
2307 rid = ntohl (zis_msg->gns_header.r_id);
2308 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2309 if (zi->request_id == rid)
2310 break;
2311 if (NULL == zi)
2312 {
2313 GNUNET_break (0);
2314 GNUNET_SERVICE_client_drop (nc->client);
2315 return;
2316 }
2317 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2318 GNUNET_free (zi);
2319 GNUNET_SERVICE_client_continue (nc->client);
2320}
2321
2322
2323/**
2324 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
2325 *
2326 * @param cls the client sending the message
2327 * @param zis_msg message from the client
2328 */
2329static void
2330handle_iteration_next (void *cls,
2331 const struct ZoneIterationNextMessage *zis_msg)
2332{
2333 struct NamestoreClient *nc = cls;
2334 struct ZoneIteration *zi;
2335 uint32_t rid;
2336 uint64_t limit;
2337
2338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2339 "Received ZONE_ITERATION_NEXT message\n");
2340 GNUNET_STATISTICS_update (statistics,
2341 "Iteration NEXT messages received",
2342 1,
2343 GNUNET_NO);
2344 rid = ntohl (zis_msg->gns_header.r_id);
2345 limit = GNUNET_ntohll (zis_msg->limit);
2346 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2347 if (zi->request_id == rid)
2348 break;
2349 if (NULL == zi)
2350 {
2351 GNUNET_break (0);
2352 GNUNET_SERVICE_client_drop (nc->client);
2353 return;
2354 }
2355 run_zone_iteration_round (zi, limit);
2356}
2357
2358
2359/**
2360 * Function called when the monitor is ready for more data, and we
2361 * should thus unblock PUT operations that were blocked on the
2362 * monitor not being ready.
2363 */
2364static void
2365monitor_unblock (struct ZoneMonitor *zm)
2366{
2367 struct StoreActivity *sa = sa_head;
2368
2369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2370 "Unblocking zone monitor %p\n", zm);
2371 while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
2372 {
2373 struct StoreActivity *sn = sa->next;
2374
2375 if (sa->zm_pos == zm)
2376 continue_store_activity (sa, GNUNET_YES);
2377 sa = sn;
2378 }
2379 if (zm->limit > zm->iteration_cnt)
2380 {
2381 zm->sa_waiting = GNUNET_NO;
2382 if (NULL != zm->sa_wait_warning)
2383 {
2384 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2385 zm->sa_wait_warning = NULL;
2386 }
2387 }
2388 else if (GNUNET_YES == zm->sa_waiting)
2389 {
2390 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2391 if (NULL != zm->sa_wait_warning)
2392 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2393 zm->sa_wait_warning =
2394 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2395 &warn_monitor_slow,
2396 zm);
2397 }
2398}
2399
2400
2401/**
2402 * Send 'sync' message to zone monitor, we're now in sync.
2403 *
2404 * @param zm monitor that is now in sync
2405 */
2406static void
2407monitor_sync (struct ZoneMonitor *zm)
2408{
2409 struct GNUNET_MQ_Envelope *env;
2410 struct GNUNET_MessageHeader *sync;
2411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2412 "Synching zone monitor %p\n", zm);
2413
2414 env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
2415 GNUNET_MQ_send (zm->nc->mq, env);
2416 /* mark iteration done */
2417 zm->in_first_iteration = GNUNET_NO;
2418 zm->iteration_cnt = 0;
2419 if ((zm->limit > 0) && (zm->sa_waiting))
2420 monitor_unblock (zm);
2421}
2422
2423
2424/**
2425 * Obtain the next datum during the zone monitor's zone initial iteration.
2426 *
2427 * @param cls zone monitor that does its initial iteration
2428 */
2429static void
2430monitor_iteration_next (void *cls);
2431
2432
2433/**
2434 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2435 *
2436 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2437 * @param seq sequence number of the record, MUST NOT BE ZERO
2438 * @param zone_key zone key of the zone
2439 * @param name name
2440 * @param rd_count number of records in @a rd
2441 * @param rd array of records
2442 */
2443static void
2444monitor_iterate_cb (void *cls,
2445 uint64_t seq,
2446 const struct GNUNET_CRYPTO_PrivateKey *zone_key,
2447 const char *name,
2448 unsigned int rd_count,
2449 const struct GNUNET_GNSRECORD_Data *rd)
2450{
2451 struct ZoneMonitor *zm = cls;
2452
2453 GNUNET_assert (0 != seq);
2454 zm->seq = seq;
2455 GNUNET_assert (NULL != name);
2456 GNUNET_STATISTICS_update (statistics,
2457 "Monitor notifications sent",
2458 1,
2459 GNUNET_NO);
2460 if (0 < send_lookup_response_with_filter (zm->nc, 0, zone_key, name,
2461 rd_count, rd, zm->filter))
2462 {
2463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2464 "Sent records.\n");
2465 zm->limit--;
2466 zm->iteration_cnt--;
2467 }
2468 else
2469 zm->run_again = GNUNET_YES;
2470 if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2471 {
2472 /* We are done with the current iteration batch, AND the
2473 client would right now accept more, so go again! */
2474 GNUNET_assert (NULL == zm->task);
2475 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2476 }
2477}
2478
2479static enum GNUNET_GenericReturnValue
2480check_monitor_start (void *cls,
2481 const struct ZoneMonitorStartMessage *zis_msg)
2482{
2483 uint16_t size;
2484 size_t key_len;
2485
2486 size = ntohs (zis_msg->header.size);
2487 key_len = ntohs (zis_msg->key_len);
2488
2489 if (size < key_len + sizeof(*zis_msg))
2490 {
2491 GNUNET_break (0);
2492 return GNUNET_SYSERR;
2493 }
2494 return GNUNET_OK;
2495}
2496
2497
2498/**
2499 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2500 *
2501 * @param cls the client sending the message
2502 * @param zis_msg message from the client
2503 */
2504static void
2505handle_monitor_start (void *cls, const struct
2506 ZoneMonitorStartMessage *zis_msg)
2507{
2508 struct GNUNET_CRYPTO_PrivateKey zone;
2509 struct NamestoreClient *nc = cls;
2510 struct ZoneMonitor *zm;
2511 size_t key_len;
2512 size_t kb_read;
2513
2514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2515 "Received ZONE_MONITOR_START message\n");
2516 zm = GNUNET_new (struct ZoneMonitor);
2517 zm->nc = nc;
2518 key_len = ntohs (zis_msg->key_len);
2519 if (0 < key_len)
2520 {
2521 if ((GNUNET_SYSERR ==
2522 GNUNET_CRYPTO_read_private_key_from_buffer (&zis_msg[1],
2523 key_len,
2524 &zone,
2525 &kb_read)) ||
2526 (kb_read != key_len))
2527 {
2528 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2529 "Error reading private key\n");
2530 GNUNET_SERVICE_client_drop (nc->client);
2531 GNUNET_free (zm);
2532 return;
2533 }
2534 zm->zone = zone;
2535 }
2536 zm->limit = 1;
2537 zm->filter = ntohs (zis_msg->filter);
2538 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2539 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2540 GNUNET_SERVICE_client_mark_monitor (nc->client);
2541 GNUNET_SERVICE_client_continue (nc->client);
2542 GNUNET_notification_context_add (monitor_nc, nc->mq);
2543 if (zm->in_first_iteration)
2544 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2545 else
2546 monitor_sync (zm);
2547}
2548
2549
2550/**
2551 * Obtain the next datum during the zone monitor's zone initial iteration.
2552 *
2553 * @param cls zone monitor that does its initial iteration
2554 */
2555static void
2556monitor_iteration_next (void *cls)
2557{
2558 struct ZoneMonitor *zm = cls;
2559 struct NamestoreClient *nc = zm->nc;
2560 int ret;
2561
2562 zm->task = NULL;
2563 GNUNET_assert (0 == zm->iteration_cnt);
2564 if (zm->limit > 16)
2565 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2566 else
2567 zm->iteration_cnt = zm->limit; /* use it all */
2568 zm->run_again = GNUNET_YES;
2569 while (GNUNET_YES == zm->run_again)
2570 {
2571 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2572 "Running iteration\n");
2573 zm->run_again = GNUNET_NO;
2574 ret = nc->GSN_database->iterate_records (nc->GSN_database->cls,
2575 (GNUNET_YES == GNUNET_is_zero (
2576 &zm->zone)) ? NULL : &zm->zone,
2577 zm->seq,
2578 zm->iteration_cnt,
2579 &monitor_iterate_cb,
2580 zm);
2581 }
2582 if (GNUNET_SYSERR == ret)
2583 {
2584 GNUNET_SERVICE_client_drop (zm->nc->client);
2585 return;
2586 }
2587 if (GNUNET_NO == ret)
2588 {
2589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2590 "Zone empty... syncing\n");
2591 /* empty zone */
2592 monitor_sync (zm);
2593 return;
2594 }
2595}
2596
2597/**
2598 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2599 *
2600 * @param cls the client sending the message
2601 * @param nm message from the client
2602 */
2603static void
2604handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2605{
2606 struct NamestoreClient *nc = cls;
2607 struct ZoneMonitor *zm;
2608 uint64_t inc;
2609
2610 inc = GNUNET_ntohll (nm->limit);
2611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2612 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2613 (unsigned long long) inc);
2614 for (zm = monitor_head; NULL != zm; zm = zm->next)
2615 if (zm->nc == nc)
2616 break;
2617 if (NULL == zm)
2618 {
2619 GNUNET_break (0);
2620 GNUNET_SERVICE_client_drop (nc->client);
2621 return;
2622 }
2623 GNUNET_SERVICE_client_continue (nc->client);
2624 if (zm->limit + inc < zm->limit)
2625 {
2626 GNUNET_break (0);
2627 GNUNET_SERVICE_client_drop (nc->client);
2628 return;
2629 }
2630 zm->limit += inc;
2631 if ((zm->in_first_iteration) && (zm->limit == inc))
2632 {
2633 /* We are still iterating, and the previous iteration must
2634 have stopped due to the client's limit, so continue it! */
2635 GNUNET_assert (NULL == zm->task);
2636 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2637 }
2638 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2639 if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2640 {
2641 monitor_unblock (zm);
2642 }
2643 else if (GNUNET_YES == zm->sa_waiting)
2644 {
2645 if (NULL != zm->sa_wait_warning)
2646 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2647 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2648 zm->sa_wait_warning =
2649 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2650 &warn_monitor_slow,
2651 zm);
2652 }
2653}
2654
2655/**
2656 * Process namestore requests.
2657 *
2658 * @param cls closure
2659 * @param cfg configuration to use
2660 * @param service the initialized service
2661 */
2662static void
2663run (void *cls,
2664 const struct GNUNET_CONFIGURATION_Handle *cfg,
2665 struct GNUNET_SERVICE_Handle *service)
2666{
2667 char *database;
2668 (void) cls;
2669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2670 return_orphaned = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2671 "namestore",
2672 "RETURN_ORPHANED");
2673 GSN_cfg = cfg;
2674 monitor_nc = GNUNET_notification_context_create (1);
2675 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2676 /* Loading database plugin */
2677 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2678 "namestore",
2679 "database",
2680 &database))
2681 {
2682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2683 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2684 return;
2685 }
2686 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
2688 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
2689 GNUNET_free (database);
2690 if (NULL == GSN_database)
2691 {
2692 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2693 "Could not load database backend `%s'\n",
2694 db_lib_name);
2695 GNUNET_free (db_lib_name);
2696 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2697 return;
2698 }
2699 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2700}
2701
2702
2703/**
2704 * Define "main" method using service macro.
2705 */
2706GNUNET_SERVICE_MAIN (
2707 "namestore",
2708 GNUNET_SERVICE_OPTION_NONE,
2709 &run,
2710 &client_connect_cb,
2711 &client_disconnect_cb,
2712 NULL,
2713 GNUNET_MQ_hd_fixed_size (tx_control,
2714 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL,
2715 struct TxControlMessage,
2716 NULL),
2717 GNUNET_MQ_hd_var_size (record_store,
2718 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2719 struct RecordStoreMessage,
2720 NULL),
2721 GNUNET_MQ_hd_var_size (record_lookup,
2722 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2723 struct LabelLookupMessage,
2724 NULL),
2725 GNUNET_MQ_hd_var_size (zone_to_name,
2726 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2727 struct ZoneToNameMessage,
2728 NULL),
2729 GNUNET_MQ_hd_var_size (iteration_start,
2730 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2731 struct ZoneIterationStartMessage,
2732 NULL),
2733 GNUNET_MQ_hd_fixed_size (iteration_next,
2734 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2735 struct ZoneIterationNextMessage,
2736 NULL),
2737 GNUNET_MQ_hd_fixed_size (iteration_stop,
2738 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2739 struct ZoneIterationStopMessage,
2740 NULL),
2741 GNUNET_MQ_hd_var_size (monitor_start,
2742 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2743 struct ZoneMonitorStartMessage,
2744 NULL),
2745 GNUNET_MQ_hd_fixed_size (monitor_next,
2746 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2747 struct ZoneMonitorNextMessage,
2748 NULL),
2749 GNUNET_MQ_handler_end ());
2750
2751
2752/* end of gnunet-service-namestore.c */