aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/gnunet-service-namestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r--src/namestore/gnunet-service-namestore.c2754
1 files changed, 0 insertions, 2754 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
deleted file mode 100644
index ed06b1dc5..000000000
--- a/src/namestore/gnunet-service-namestore.c
+++ /dev/null
@@ -1,2754 +0,0 @@
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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_PrivateKey *zone)
541{
542 struct GNUNET_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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_IDENTITY_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 size_t body_len;
1742 struct StoreActivity *sa;
1743 struct RecordSet *rs;
1744 enum GNUNET_ErrorCode res;
1745
1746 key_len = ntohs (rp_msg->key_len);
1747 rp_msg_len = ntohs (rp_msg->gns_header.header.size);
1748 body_len = rp_msg_len - sizeof (*rp_msg);
1749 rs_off = sizeof (*rp_msg) + key_len;
1750 rs_len = rp_msg_len - rs_off;
1751 if ((GNUNET_SYSERR ==
1752 GNUNET_IDENTITY_read_private_key_from_buffer (&rp_msg[1],
1753 key_len,
1754 &zone,
1755 &kb_read)) ||
1756 (kb_read != key_len))
1757 {
1758 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1759 "Error reading private key\n");
1760 GNUNET_SERVICE_client_drop (nc->client);
1761 return;
1762 }
1763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1764 "Received NAMESTORE_RECORD_STORE message\n");
1765 rid = ntohl (rp_msg->gns_header.r_id);
1766 rd_set_count = ntohs (rp_msg->rd_set_count);
1767 buf = (const char *) rp_msg + rs_off;
1768 for (int i = 0; i < rd_set_count; i++)
1769 {
1770 rs = (struct RecordSet *) buf;
1771 res = store_record_set (nc, &zone,
1772 rs, &read);
1773 if (GNUNET_EC_NONE != res)
1774 {
1775 send_store_response (nc, res, rid);
1776 GNUNET_SERVICE_client_continue (nc->client);
1777 return;
1778 }
1779 buf += read;
1780 }
1781 sa = GNUNET_malloc (sizeof(struct StoreActivity) + rs_len);
1782 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1783 sa->nc = nc;
1784 sa->rs = (struct RecordSet *) &sa[1];
1785 sa->rd_set_count = rd_set_count;
1786 GNUNET_memcpy (&sa[1], (char *) rp_msg + rs_off, rs_len);
1787 sa->rid = rid;
1788 sa->rd_set_pos = 0;
1789 sa->private_key = zone;
1790 sa->zm_pos = monitor_head;
1791 sa->uncommited = nc->in_transaction;
1792 continue_store_activity (sa, GNUNET_YES);
1793}
1794
1795static void
1796send_tx_response (int rid, enum GNUNET_ErrorCode ec, struct NamestoreClient *nc)
1797{
1798 struct TxControlResultMessage *txr_msg;
1799 struct GNUNET_MQ_Envelope *env;
1800
1801 env =
1802 GNUNET_MQ_msg (txr_msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT);
1803 txr_msg->gns_header.r_id = rid;
1804 txr_msg->ec = htonl (ec);
1805 GNUNET_MQ_send (nc->mq, env);
1806}
1807
1808/**
1809 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL message
1810 *
1811 * @param cls client sending the message
1812 * @param tx_msg message of type `struct TxControlMessage`
1813 */
1814static void
1815handle_tx_control (void *cls, const struct TxControlMessage *tx_msg)
1816{
1817 struct NamestoreClient *nc = cls;
1818 struct StoreActivity *sa = sa_head;
1819 struct StoreActivity *sn;
1820 enum GNUNET_GenericReturnValue ret;
1821 char *emsg = NULL;
1822 int blocked = GNUNET_NO;
1823
1824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received TX_CONTROL message\n");
1825
1826 switch (ntohs (tx_msg->control))
1827 {
1828 case GNUNET_NAMESTORE_TX_BEGIN:
1829 ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls,
1830 &emsg);
1831 send_tx_response (tx_msg->gns_header.r_id,
1832 (GNUNET_SYSERR == ret) ?
1833 GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, nc);
1834 if (GNUNET_SYSERR == ret)
1835 {
1836 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1837 "Databse backend error: `%s'", emsg);
1838 GNUNET_free (emsg);
1839 }
1840 GNUNET_SERVICE_client_continue (nc->client);
1841 nc->in_transaction = GNUNET_YES;
1842 break;
1843 case GNUNET_NAMESTORE_TX_COMMIT:
1844 ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls,
1845 &emsg);
1846 send_tx_response (tx_msg->gns_header.r_id,
1847 (GNUNET_SYSERR == ret) ?
1848 GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE,
1849 nc);
1850 if (GNUNET_SYSERR == ret)
1851 {
1852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1853 "Databse backend error: `%s'", emsg);
1854 GNUNET_free (emsg);
1855 }
1856 if (GNUNET_SYSERR != ret)
1857 {
1858 nc->in_transaction = GNUNET_NO;
1859 while (NULL != sa)
1860 {
1861 if ((nc != sa->nc) ||
1862 (GNUNET_NO == sa->uncommited))
1863 {
1864 sa = sa->next;
1865 continue;
1866 }
1867 sa->uncommited = GNUNET_NO;
1868 sn = sa->next;
1869 if (GNUNET_OK != continue_store_activity (sa, GNUNET_NO))
1870 blocked = GNUNET_YES;
1871 sa = sn;
1872 }
1873 if (GNUNET_YES != blocked)
1874 GNUNET_SERVICE_client_continue (nc->client);
1875 }
1876 break;
1877 case GNUNET_NAMESTORE_TX_ROLLBACK:
1878 ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls,
1879 &emsg);
1880 send_tx_response (tx_msg->gns_header.r_id,
1881 (GNUNET_SYSERR == ret) ?
1882 GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, nc);
1883 GNUNET_SERVICE_client_continue (nc->client);
1884 if (GNUNET_SYSERR == ret)
1885 {
1886 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1887 "Databse backend error: `%s'", emsg);
1888 GNUNET_free (emsg);
1889 }
1890 if (GNUNET_SYSERR != ret)
1891 {
1892 nc->in_transaction = GNUNET_NO;
1893 while (NULL != sa)
1894 {
1895 if ((nc != sa->nc) ||
1896 (GNUNET_NO == sa->uncommited))
1897 {
1898 sa = sa->next;
1899 continue;
1900 }
1901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1902 "Discarding uncommited StoreActivity\n");
1903 sn = sa->next;
1904 free_store_activity (sa);
1905 sa = sn;
1906 }
1907 }
1908 break;
1909 default:
1910 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1911 "Unknown control type %u\n", ntohs (tx_msg->control));
1912 GNUNET_break (0);
1913 }
1914}
1915
1916/**
1917 * Context for record remove operations passed from #handle_zone_to_name to
1918 * #handle_zone_to_name_it as closure
1919 */
1920struct ZoneToNameCtx
1921{
1922 /**
1923 * Namestore client
1924 */
1925 struct NamestoreClient *nc;
1926
1927 /**
1928 * Request id (to be used in the response to the client).
1929 */
1930 uint32_t rid;
1931
1932 /**
1933 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1934 * not finding a name for the zone still counts as a 'success' here,
1935 * as this field is about the success of executing the IPC protocol.
1936 */
1937 enum GNUNET_ErrorCode ec;
1938};
1939
1940
1941/**
1942 * Zone to name iterator
1943 *
1944 * @param cls struct ZoneToNameCtx *
1945 * @param seq sequence number of the record, MUST NOT BE ZERO
1946 * @param zone_key the zone key
1947 * @param name name
1948 * @param rd_count number of records in @a rd
1949 * @param rd record data
1950 */
1951static void
1952handle_zone_to_name_it (void *cls,
1953 uint64_t seq,
1954 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1955 const char *name,
1956 unsigned int rd_count,
1957 const struct GNUNET_GNSRECORD_Data *rd)
1958{
1959 struct ZoneToNameCtx *ztn_ctx = cls;
1960 struct GNUNET_MQ_Envelope *env;
1961 struct ZoneToNameResponseMessage *ztnr_msg;
1962 size_t name_len;
1963 size_t key_len;
1964 ssize_t rd_ser_len;
1965 size_t msg_size;
1966 char *name_tmp;
1967 char *rd_tmp;
1968
1969 GNUNET_assert (0 != seq);
1970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1971 "Found result for zone-to-name lookup: `%s'\n",
1972 name);
1973 ztn_ctx->ec = GNUNET_EC_NONE;
1974 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1975 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1976 if (rd_ser_len < 0)
1977 {
1978 GNUNET_break (0);
1979 ztn_ctx->ec = htonl (GNUNET_EC_NAMESTORE_UNKNOWN);
1980 return;
1981 }
1982 key_len = GNUNET_IDENTITY_private_key_get_length (zone_key);
1983 msg_size = sizeof(struct ZoneToNameResponseMessage)
1984 + name_len + rd_ser_len + key_len;
1985 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1986 {
1987 GNUNET_break (0);
1988 ztn_ctx->ec = GNUNET_EC_NAMESTORE_RECORD_TOO_BIG;
1989 return;
1990 }
1991 env =
1992 GNUNET_MQ_msg_extra (ztnr_msg,
1993 key_len + name_len + rd_ser_len,
1994 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1995 ztnr_msg->gns_header.header.size = htons (msg_size);
1996 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1997 ztnr_msg->ec = htonl (ztn_ctx->ec);
1998 ztnr_msg->rd_len = htons (rd_ser_len);
1999 ztnr_msg->rd_count = htons (rd_count);
2000 ztnr_msg->name_len = htons (name_len);
2001 ztnr_msg->key_len = htons (key_len);
2002 GNUNET_IDENTITY_write_private_key_to_buffer (zone_key,
2003 &ztnr_msg[1],
2004 key_len);
2005 name_tmp = (char *) &ztnr_msg[1] + key_len;
2006 GNUNET_memcpy (name_tmp, name, name_len);
2007 rd_tmp = &name_tmp[name_len];
2008 GNUNET_assert (
2009 rd_ser_len ==
2010 GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
2011 ztn_ctx->ec = GNUNET_EC_NONE;
2012 GNUNET_MQ_send (ztn_ctx->nc->mq, env);
2013}
2014
2015static enum GNUNET_GenericReturnValue
2016check_zone_to_name (void *cls,
2017 const struct ZoneToNameMessage *zis_msg)
2018{
2019 return GNUNET_OK;
2020}
2021
2022
2023/**
2024 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
2025 *
2026 * @param cls client client sending the message
2027 * @param ztn_msg message of type 'struct ZoneToNameMessage'
2028 */
2029static void
2030handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
2031{
2032 struct GNUNET_IDENTITY_PrivateKey zone;
2033 struct GNUNET_IDENTITY_PublicKey value_zone;
2034 struct NamestoreClient *nc = cls;
2035 struct ZoneToNameCtx ztn_ctx;
2036 struct GNUNET_MQ_Envelope *env;
2037 struct ZoneToNameResponseMessage *ztnr_msg;
2038 size_t key_len;
2039 size_t pkey_len;
2040 size_t kb_read;
2041
2042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
2043 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
2044 ztn_ctx.nc = nc;
2045 ztn_ctx.ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND;
2046 key_len = ntohs (ztn_msg->key_len);
2047 if ((GNUNET_SYSERR ==
2048 GNUNET_IDENTITY_read_private_key_from_buffer (&ztn_msg[1],
2049 key_len,
2050 &zone,
2051 &kb_read)) ||
2052 (kb_read != key_len))
2053 {
2054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2055 "Error parsing private key.\n");
2056 GNUNET_SERVICE_client_drop (nc->client);
2057 GNUNET_break (0);
2058 return;
2059 }
2060 pkey_len = ntohs (ztn_msg->pkey_len);
2061 if ((GNUNET_SYSERR ==
2062 GNUNET_IDENTITY_read_public_key_from_buffer ((char*) &ztn_msg[1]
2063 + key_len,
2064 pkey_len,
2065 &value_zone,
2066 &kb_read)) ||
2067 (kb_read != pkey_len))
2068 {
2069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2070 "Error parsing public key.\n");
2071 GNUNET_SERVICE_client_drop (nc->client);
2072 GNUNET_break (0);
2073 return;
2074 }
2075 if (GNUNET_SYSERR == nc->GSN_database->zone_to_name (nc->GSN_database->cls,
2076 &zone,
2077 &value_zone,
2078 &handle_zone_to_name_it,
2079 &ztn_ctx))
2080 {
2081 /* internal error, hang up instead of signalling something
2082 that might be wrong */
2083 GNUNET_break (0);
2084 GNUNET_SERVICE_client_drop (nc->client);
2085 return;
2086 }
2087 if (GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND == ztn_ctx.ec)
2088 {
2089 /* no result found, send empty response */
2090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2091 "Found no result for zone-to-name lookup.\n");
2092 env = GNUNET_MQ_msg (ztnr_msg,
2093 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
2094 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
2095 ztnr_msg->ec = htonl (GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND);
2096 GNUNET_MQ_send (nc->mq, env);
2097 }
2098 GNUNET_SERVICE_client_continue (nc->client);
2099}
2100
2101
2102/**
2103 * Context for record remove operations passed from
2104 * #run_zone_iteration_round to #zone_iterate_proc as closure
2105 */
2106struct ZoneIterationProcResult
2107{
2108 /**
2109 * The zone iteration handle
2110 */
2111 struct ZoneIteration *zi;
2112
2113 /**
2114 * Number of results left to be returned in this iteration.
2115 */
2116 uint64_t limit;
2117
2118 /**
2119 * Skip a result and run again unless GNUNET_NO
2120 */
2121 int run_again;
2122};
2123
2124
2125/**
2126 * Process results for zone iteration from database
2127 *
2128 * @param cls struct ZoneIterationProcResult
2129 * @param seq sequence number of the record, MUST NOT BE ZERO
2130 * @param zone_key the zone key
2131 * @param name name
2132 * @param rd_count number of records for this name
2133 * @param rd record data
2134 */
2135static void
2136zone_iterate_proc (void *cls,
2137 uint64_t seq,
2138 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2139 const char *name,
2140 unsigned int rd_count,
2141 const struct GNUNET_GNSRECORD_Data *rd)
2142{
2143 struct ZoneIterationProcResult *proc = cls;
2144
2145 GNUNET_assert (0 != seq);
2146 if ((NULL == zone_key) && (NULL == name))
2147 {
2148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
2149 return;
2150 }
2151 if ((NULL == zone_key) || (NULL == name))
2152 {
2153 /* what is this!? should never happen */
2154 GNUNET_break (0);
2155 return;
2156 }
2157 if (0 == proc->limit)
2158 {
2159 /* what is this!? should never happen */
2160 GNUNET_break (0);
2161 return;
2162 }
2163 proc->zi->seq = seq;
2164 if (0 < send_lookup_response_with_filter (proc->zi->nc,
2165 proc->zi->request_id,
2166 zone_key,
2167 name,
2168 rd_count,
2169 rd,
2170 proc->zi->filter))
2171 proc->limit--;
2172 else
2173 proc->run_again = GNUNET_YES;
2174}
2175
2176
2177/**
2178 * Perform the next round of the zone iteration.
2179 *
2180 * @param zi zone iterator to process
2181 * @param limit number of results to return in one pass
2182 */
2183static void
2184run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
2185{
2186 struct ZoneIterationProcResult proc;
2187 struct GNUNET_TIME_Absolute start;
2188 struct GNUNET_TIME_Relative duration;
2189 struct NamestoreClient *nc = zi->nc;
2190
2191 memset (&proc, 0, sizeof(proc));
2192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2193 "Asked to return up to %llu records at position %llu\n",
2194 (unsigned long long) limit,
2195 (unsigned long long) zi->seq);
2196 proc.zi = zi;
2197 proc.limit = limit;
2198 proc.run_again = GNUNET_YES;
2199 start = GNUNET_TIME_absolute_get ();
2200 while (GNUNET_YES == proc.run_again)
2201 {
2202 proc.run_again = GNUNET_NO;
2203 GNUNET_break (GNUNET_SYSERR !=
2204 nc->GSN_database->iterate_records (nc->GSN_database->cls,
2205 (GNUNET_YES ==
2206 GNUNET_is_zero (
2207 &zi->zone))
2208 ? NULL
2209 : &zi->zone,
2210 zi->seq,
2211 proc.limit,
2212 &zone_iterate_proc,
2213 &proc));
2214 }
2215 duration = GNUNET_TIME_absolute_get_duration (start);
2216 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
2217 GNUNET_STATISTICS_set (statistics,
2218 "NAMESTORE iteration delay (μs/record)",
2219 duration.rel_value_us,
2220 GNUNET_NO);
2221 if (0 == proc.limit)
2222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2223 "Returned %llu results, more results available\n",
2224 (unsigned long long) limit);
2225 zi->send_end = (0 != proc.limit);
2226 if (0 == zi->cache_ops)
2227 zone_iteration_done_client_continue (zi);
2228}
2229
2230static enum GNUNET_GenericReturnValue
2231check_iteration_start (void *cls,
2232 const struct ZoneIterationStartMessage *zis_msg)
2233{
2234 uint16_t size;
2235 size_t key_len;
2236
2237 size = ntohs (zis_msg->gns_header.header.size);
2238 key_len = ntohs (zis_msg->key_len);
2239
2240 if (size < key_len + sizeof(*zis_msg))
2241 {
2242 GNUNET_break (0);
2243 return GNUNET_SYSERR;
2244 }
2245 return GNUNET_OK;
2246}
2247
2248
2249/**
2250 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
2251 *
2252 * @param cls the client sending the message
2253 * @param zis_msg message from the client
2254 */
2255static void
2256handle_iteration_start (void *cls,
2257 const struct ZoneIterationStartMessage *zis_msg)
2258{
2259 struct GNUNET_IDENTITY_PrivateKey zone;
2260 struct NamestoreClient *nc = cls;
2261 struct ZoneIteration *zi;
2262 size_t key_len;
2263 size_t kb_read;
2264
2265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2266 "Received ZONE_ITERATION_START message\n");
2267 key_len = ntohs (zis_msg->key_len);
2268 zi = GNUNET_new (struct ZoneIteration);
2269 if (0 < key_len)
2270 {
2271 if ((GNUNET_SYSERR ==
2272 GNUNET_IDENTITY_read_private_key_from_buffer (&zis_msg[1],
2273 key_len,
2274 &zone,
2275 &kb_read)) ||
2276 (kb_read != key_len))
2277 {
2278 GNUNET_SERVICE_client_drop (nc->client);
2279 GNUNET_free (zi);
2280 return;
2281 }
2282 zi->zone = zone;
2283 }
2284 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2285 zi->filter = ntohs (zis_msg->filter);
2286 zi->offset = 0;
2287 zi->nc = nc;
2288 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2289 run_zone_iteration_round (zi, 1);
2290}
2291
2292
2293/**
2294 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
2295 *
2296 * @param cls the client sending the message
2297 * @param zis_msg message from the client
2298 */
2299static void
2300handle_iteration_stop (void *cls,
2301 const struct ZoneIterationStopMessage *zis_msg)
2302{
2303 struct NamestoreClient *nc = cls;
2304 struct ZoneIteration *zi;
2305 uint32_t rid;
2306
2307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2308 "Received ZONE_ITERATION_STOP message\n");
2309 rid = ntohl (zis_msg->gns_header.r_id);
2310 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2311 if (zi->request_id == rid)
2312 break;
2313 if (NULL == zi)
2314 {
2315 GNUNET_break (0);
2316 GNUNET_SERVICE_client_drop (nc->client);
2317 return;
2318 }
2319 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2320 GNUNET_free (zi);
2321 GNUNET_SERVICE_client_continue (nc->client);
2322}
2323
2324
2325/**
2326 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
2327 *
2328 * @param cls the client sending the message
2329 * @param zis_msg message from the client
2330 */
2331static void
2332handle_iteration_next (void *cls,
2333 const struct ZoneIterationNextMessage *zis_msg)
2334{
2335 struct NamestoreClient *nc = cls;
2336 struct ZoneIteration *zi;
2337 uint32_t rid;
2338 uint64_t limit;
2339
2340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2341 "Received ZONE_ITERATION_NEXT message\n");
2342 GNUNET_STATISTICS_update (statistics,
2343 "Iteration NEXT messages received",
2344 1,
2345 GNUNET_NO);
2346 rid = ntohl (zis_msg->gns_header.r_id);
2347 limit = GNUNET_ntohll (zis_msg->limit);
2348 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2349 if (zi->request_id == rid)
2350 break;
2351 if (NULL == zi)
2352 {
2353 GNUNET_break (0);
2354 GNUNET_SERVICE_client_drop (nc->client);
2355 return;
2356 }
2357 run_zone_iteration_round (zi, limit);
2358}
2359
2360
2361/**
2362 * Function called when the monitor is ready for more data, and we
2363 * should thus unblock PUT operations that were blocked on the
2364 * monitor not being ready.
2365 */
2366static void
2367monitor_unblock (struct ZoneMonitor *zm)
2368{
2369 struct StoreActivity *sa = sa_head;
2370
2371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2372 "Unblocking zone monitor %p\n", zm);
2373 while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
2374 {
2375 struct StoreActivity *sn = sa->next;
2376
2377 if (sa->zm_pos == zm)
2378 continue_store_activity (sa, GNUNET_YES);
2379 sa = sn;
2380 }
2381 if (zm->limit > zm->iteration_cnt)
2382 {
2383 zm->sa_waiting = GNUNET_NO;
2384 if (NULL != zm->sa_wait_warning)
2385 {
2386 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2387 zm->sa_wait_warning = NULL;
2388 }
2389 }
2390 else if (GNUNET_YES == zm->sa_waiting)
2391 {
2392 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2393 if (NULL != zm->sa_wait_warning)
2394 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2395 zm->sa_wait_warning =
2396 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2397 &warn_monitor_slow,
2398 zm);
2399 }
2400}
2401
2402
2403/**
2404 * Send 'sync' message to zone monitor, we're now in sync.
2405 *
2406 * @param zm monitor that is now in sync
2407 */
2408static void
2409monitor_sync (struct ZoneMonitor *zm)
2410{
2411 struct GNUNET_MQ_Envelope *env;
2412 struct GNUNET_MessageHeader *sync;
2413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2414 "Synching zone monitor %p\n", zm);
2415
2416 env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
2417 GNUNET_MQ_send (zm->nc->mq, env);
2418 /* mark iteration done */
2419 zm->in_first_iteration = GNUNET_NO;
2420 zm->iteration_cnt = 0;
2421 if ((zm->limit > 0) && (zm->sa_waiting))
2422 monitor_unblock (zm);
2423}
2424
2425
2426/**
2427 * Obtain the next datum during the zone monitor's zone initial iteration.
2428 *
2429 * @param cls zone monitor that does its initial iteration
2430 */
2431static void
2432monitor_iteration_next (void *cls);
2433
2434
2435/**
2436 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2437 *
2438 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2439 * @param seq sequence number of the record, MUST NOT BE ZERO
2440 * @param zone_key zone key of the zone
2441 * @param name name
2442 * @param rd_count number of records in @a rd
2443 * @param rd array of records
2444 */
2445static void
2446monitor_iterate_cb (void *cls,
2447 uint64_t seq,
2448 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2449 const char *name,
2450 unsigned int rd_count,
2451 const struct GNUNET_GNSRECORD_Data *rd)
2452{
2453 struct ZoneMonitor *zm = cls;
2454
2455 GNUNET_assert (0 != seq);
2456 zm->seq = seq;
2457 GNUNET_assert (NULL != name);
2458 GNUNET_STATISTICS_update (statistics,
2459 "Monitor notifications sent",
2460 1,
2461 GNUNET_NO);
2462 if (0 < send_lookup_response_with_filter (zm->nc, 0, zone_key, name,
2463 rd_count, rd, zm->filter))
2464 {
2465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2466 "Sent records.\n");
2467 zm->limit--;
2468 zm->iteration_cnt--;
2469 }
2470 else
2471 zm->run_again = GNUNET_YES;
2472 if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2473 {
2474 /* We are done with the current iteration batch, AND the
2475 client would right now accept more, so go again! */
2476 GNUNET_assert (NULL == zm->task);
2477 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2478 }
2479}
2480
2481static enum GNUNET_GenericReturnValue
2482check_monitor_start (void *cls,
2483 const struct ZoneMonitorStartMessage *zis_msg)
2484{
2485 uint16_t size;
2486 size_t key_len;
2487
2488 size = ntohs (zis_msg->header.size);
2489 key_len = ntohs (zis_msg->key_len);
2490
2491 if (size < key_len + sizeof(*zis_msg))
2492 {
2493 GNUNET_break (0);
2494 return GNUNET_SYSERR;
2495 }
2496 return GNUNET_OK;
2497}
2498
2499
2500/**
2501 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2502 *
2503 * @param cls the client sending the message
2504 * @param zis_msg message from the client
2505 */
2506static void
2507handle_monitor_start (void *cls, const struct
2508 ZoneMonitorStartMessage *zis_msg)
2509{
2510 struct GNUNET_IDENTITY_PrivateKey zone;
2511 struct NamestoreClient *nc = cls;
2512 struct ZoneMonitor *zm;
2513 size_t key_len;
2514 size_t kb_read;
2515
2516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2517 "Received ZONE_MONITOR_START message\n");
2518 zm = GNUNET_new (struct ZoneMonitor);
2519 zm->nc = nc;
2520 key_len = ntohs (zis_msg->key_len);
2521 if (0 < key_len)
2522 {
2523 if ((GNUNET_SYSERR ==
2524 GNUNET_IDENTITY_read_private_key_from_buffer (&zis_msg[1],
2525 key_len,
2526 &zone,
2527 &kb_read)) ||
2528 (kb_read != key_len))
2529 {
2530 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2531 "Error reading private key\n");
2532 GNUNET_SERVICE_client_drop (nc->client);
2533 GNUNET_free (zm);
2534 return;
2535 }
2536 zm->zone = zone;
2537 }
2538 zm->limit = 1;
2539 zm->filter = ntohs (zis_msg->filter);
2540 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2541 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2542 GNUNET_SERVICE_client_mark_monitor (nc->client);
2543 GNUNET_SERVICE_client_continue (nc->client);
2544 GNUNET_notification_context_add (monitor_nc, nc->mq);
2545 if (zm->in_first_iteration)
2546 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2547 else
2548 monitor_sync (zm);
2549}
2550
2551
2552/**
2553 * Obtain the next datum during the zone monitor's zone initial iteration.
2554 *
2555 * @param cls zone monitor that does its initial iteration
2556 */
2557static void
2558monitor_iteration_next (void *cls)
2559{
2560 struct ZoneMonitor *zm = cls;
2561 struct NamestoreClient *nc = zm->nc;
2562 int ret;
2563
2564 zm->task = NULL;
2565 GNUNET_assert (0 == zm->iteration_cnt);
2566 if (zm->limit > 16)
2567 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2568 else
2569 zm->iteration_cnt = zm->limit; /* use it all */
2570 zm->run_again = GNUNET_YES;
2571 while (GNUNET_YES == zm->run_again)
2572 {
2573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2574 "Running iteration\n");
2575 zm->run_again = GNUNET_NO;
2576 ret = nc->GSN_database->iterate_records (nc->GSN_database->cls,
2577 (GNUNET_YES == GNUNET_is_zero (
2578 &zm->zone)) ? NULL : &zm->zone,
2579 zm->seq,
2580 zm->iteration_cnt,
2581 &monitor_iterate_cb,
2582 zm);
2583 }
2584 if (GNUNET_SYSERR == ret)
2585 {
2586 GNUNET_SERVICE_client_drop (zm->nc->client);
2587 return;
2588 }
2589 if (GNUNET_NO == ret)
2590 {
2591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2592 "Zone empty... syncing\n");
2593 /* empty zone */
2594 monitor_sync (zm);
2595 return;
2596 }
2597}
2598
2599/**
2600 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2601 *
2602 * @param cls the client sending the message
2603 * @param nm message from the client
2604 */
2605static void
2606handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2607{
2608 struct NamestoreClient *nc = cls;
2609 struct ZoneMonitor *zm;
2610 uint64_t inc;
2611
2612 inc = GNUNET_ntohll (nm->limit);
2613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2614 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2615 (unsigned long long) inc);
2616 for (zm = monitor_head; NULL != zm; zm = zm->next)
2617 if (zm->nc == nc)
2618 break;
2619 if (NULL == zm)
2620 {
2621 GNUNET_break (0);
2622 GNUNET_SERVICE_client_drop (nc->client);
2623 return;
2624 }
2625 GNUNET_SERVICE_client_continue (nc->client);
2626 if (zm->limit + inc < zm->limit)
2627 {
2628 GNUNET_break (0);
2629 GNUNET_SERVICE_client_drop (nc->client);
2630 return;
2631 }
2632 zm->limit += inc;
2633 if ((zm->in_first_iteration) && (zm->limit == inc))
2634 {
2635 /* We are still iterating, and the previous iteration must
2636 have stopped due to the client's limit, so continue it! */
2637 GNUNET_assert (NULL == zm->task);
2638 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2639 }
2640 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2641 if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2642 {
2643 monitor_unblock (zm);
2644 }
2645 else if (GNUNET_YES == zm->sa_waiting)
2646 {
2647 if (NULL != zm->sa_wait_warning)
2648 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2649 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2650 zm->sa_wait_warning =
2651 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2652 &warn_monitor_slow,
2653 zm);
2654 }
2655}
2656
2657/**
2658 * Process namestore requests.
2659 *
2660 * @param cls closure
2661 * @param cfg configuration to use
2662 * @param service the initialized service
2663 */
2664static void
2665run (void *cls,
2666 const struct GNUNET_CONFIGURATION_Handle *cfg,
2667 struct GNUNET_SERVICE_Handle *service)
2668{
2669 char *database;
2670 (void) cls;
2671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2672 return_orphaned = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2673 "namestore",
2674 "RETURN_ORPHANED");
2675 GSN_cfg = cfg;
2676 monitor_nc = GNUNET_notification_context_create (1);
2677 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2678 /* Loading database plugin */
2679 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2680 "namestore",
2681 "database",
2682 &database))
2683 {
2684 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2685 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2686 return;
2687 }
2688 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
2690 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
2691 GNUNET_free (database);
2692 if (NULL == GSN_database)
2693 {
2694 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2695 "Could not load database backend `%s'\n",
2696 db_lib_name);
2697 GNUNET_free (db_lib_name);
2698 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2699 return;
2700 }
2701 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2702}
2703
2704
2705/**
2706 * Define "main" method using service macro.
2707 */
2708GNUNET_SERVICE_MAIN (
2709 "namestore",
2710 GNUNET_SERVICE_OPTION_NONE,
2711 &run,
2712 &client_connect_cb,
2713 &client_disconnect_cb,
2714 NULL,
2715 GNUNET_MQ_hd_fixed_size (tx_control,
2716 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL,
2717 struct TxControlMessage,
2718 NULL),
2719 GNUNET_MQ_hd_var_size (record_store,
2720 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2721 struct RecordStoreMessage,
2722 NULL),
2723 GNUNET_MQ_hd_var_size (record_lookup,
2724 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2725 struct LabelLookupMessage,
2726 NULL),
2727 GNUNET_MQ_hd_var_size (zone_to_name,
2728 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2729 struct ZoneToNameMessage,
2730 NULL),
2731 GNUNET_MQ_hd_var_size (iteration_start,
2732 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2733 struct ZoneIterationStartMessage,
2734 NULL),
2735 GNUNET_MQ_hd_fixed_size (iteration_next,
2736 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2737 struct ZoneIterationNextMessage,
2738 NULL),
2739 GNUNET_MQ_hd_fixed_size (iteration_stop,
2740 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2741 struct ZoneIterationStopMessage,
2742 NULL),
2743 GNUNET_MQ_hd_var_size (monitor_start,
2744 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2745 struct ZoneMonitorStartMessage,
2746 NULL),
2747 GNUNET_MQ_hd_fixed_size (monitor_next,
2748 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2749 struct ZoneMonitorNextMessage,
2750 NULL),
2751 GNUNET_MQ_handler_end ());
2752
2753
2754/* end of gnunet-service-namestore.c */