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.c2276
1 files changed, 0 insertions, 2276 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
deleted file mode 100644
index cd953492e..000000000
--- a/src/namestore/gnunet-service-namestore.c
+++ /dev/null
@@ -1,2276 +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_dnsparser_lib.h"
30#include "gnunet_gns_service.h"
31#include "gnunet_namecache_service.h"
32#include "gnunet_namestore_service.h"
33#include "gnunet_namestore_plugin.h"
34#include "gnunet_statistics_service.h"
35#include "gnunet_signatures.h"
36#include "namestore.h"
37
38#define LOG_STRERROR_FILE(kind, syscall, filename) \
39 GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
40
41/**
42 * If a monitor takes more than 1 minute to process an event, print a warning.
43 */
44#define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
45
46/**
47 * Size of the cache used by #get_nick_record()
48 */
49#define NC_SIZE 16
50
51/**
52 * A namestore client
53 */
54struct NamestoreClient;
55
56
57/**
58 * A namestore iteration operation.
59 */
60struct ZoneIteration
61{
62 /**
63 * Next element in the DLL
64 */
65 struct ZoneIteration *next;
66
67 /**
68 * Previous element in the DLL
69 */
70 struct ZoneIteration *prev;
71
72 /**
73 * Namestore client which intiated this zone iteration
74 */
75 struct NamestoreClient *nc;
76
77 /**
78 * The nick to add to the records
79 */
80 struct GNUNET_GNSRECORD_Data *nick;
81
82 /**
83 * Key of the zone we are iterating over.
84 */
85 struct GNUNET_IDENTITY_PrivateKey zone;
86
87 /**
88 * Last sequence number in the zone iteration used to address next
89 * result of the zone iteration in the store
90 *
91 * Initially set to 0.
92 * Updated in #zone_iterate_proc()
93 */
94 uint64_t seq;
95
96 /**
97 * The operation id for the zone iteration in the response for the client
98 */
99 uint32_t request_id;
100
101 /**
102 * Offset of the zone iteration used to address next result of the zone
103 * iteration in the store
104 *
105 * Initially set to 0 in #handle_iteration_start
106 * Incremented with by every call to #handle_iteration_next
107 */
108 uint32_t offset;
109
110 /**
111 * Number of pending cache operations triggered by this zone iteration which we
112 * need to wait for before allowing the client to continue.
113 */
114 unsigned int cache_ops;
115
116 /**
117 * Set to #GNUNET_YES if the last iteration exhausted the limit set by the
118 * client and we should send the #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
119 * message and free the data structure once @e cache_ops is zero.
120 */
121 int send_end;
122};
123
124
125/**
126 * A namestore client
127 */
128struct NamestoreClient
129{
130 /**
131 * The client
132 */
133 struct GNUNET_SERVICE_Client *client;
134
135 /**
136 * Message queue for transmission to @e client
137 */
138 struct GNUNET_MQ_Handle *mq;
139
140 /**
141 * Head of the DLL of
142 * Zone iteration operations in progress initiated by this client
143 */
144 struct ZoneIteration *op_head;
145
146 /**
147 * Tail of the DLL of
148 * Zone iteration operations in progress initiated by this client
149 */
150 struct ZoneIteration *op_tail;
151};
152
153
154/**
155 * A namestore monitor.
156 */
157struct ZoneMonitor
158{
159 /**
160 * Next element in the DLL
161 */
162 struct ZoneMonitor *next;
163
164 /**
165 * Previous element in the DLL
166 */
167 struct ZoneMonitor *prev;
168
169 /**
170 * Namestore client which intiated this zone monitor
171 */
172 struct NamestoreClient *nc;
173
174 /**
175 * Private key of the zone.
176 */
177 struct GNUNET_IDENTITY_PrivateKey zone;
178
179 /**
180 * Task active during initial iteration.
181 */
182 struct GNUNET_SCHEDULER_Task *task;
183
184 /**
185 * Task to warn about slow monitors.
186 */
187 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
188
189 /**
190 * Since when are we blocked on this monitor?
191 */
192 struct GNUNET_TIME_Absolute sa_waiting_start;
193
194 /**
195 * Last sequence number in the zone iteration used to address next
196 * result of the zone iteration in the store
197 *
198 * Initially set to 0.
199 * Updated in #monitor_iterate_cb()
200 */
201 uint64_t seq;
202
203 /**
204 * Current limit of how many more messages we are allowed
205 * to queue to this monitor.
206 */
207 uint64_t limit;
208
209 /**
210 * How many more requests may we receive from the iterator
211 * before it is at the limit we gave it? Will be below or
212 * equal to @e limit. The effective limit for monitor
213 * events is thus @e iteration_cnt - @e limit!
214 */
215 uint64_t iteration_cnt;
216
217 /**
218 * Are we (still) in the initial iteration pass?
219 */
220 int in_first_iteration;
221
222 /**
223 * Is there a store activity waiting for this monitor? We only raise the
224 * flag when it happens and search the DLL for the store activity when we
225 * had a limit increase. If we cannot find any waiting store activity at
226 * that time, we clear the flag again.
227 */
228 int sa_waiting;
229};
230
231
232/**
233 * Pending operation on the namecache.
234 */
235struct CacheOperation
236{
237 /**
238 * Kept in a DLL.
239 */
240 struct CacheOperation *prev;
241
242 /**
243 * Kept in a DLL.
244 */
245 struct CacheOperation *next;
246
247 /**
248 * Handle to namecache queue.
249 */
250 struct GNUNET_NAMECACHE_QueueEntry *qe;
251
252 /**
253 * Client to notify about the result, can be NULL.
254 */
255 struct NamestoreClient *nc;
256
257 /**
258 * Zone iteration to call #zone_iteration_done_client_continue()
259 * for if applicable, can be NULL.
260 */
261 struct ZoneIteration *zi;
262
263 /**
264 * Client's request ID.
265 */
266 uint32_t rid;
267};
268
269
270/**
271 * Information for an ongoing #handle_record_store() operation.
272 * Needed as we may wait for monitors to be ready for the notification.
273 */
274struct StoreActivity
275{
276 /**
277 * Kept in a DLL.
278 */
279 struct StoreActivity *next;
280
281 /**
282 * Kept in a DLL.
283 */
284 struct StoreActivity *prev;
285
286 /**
287 * Which client triggered the store activity?
288 */
289 struct NamestoreClient *nc;
290
291 /**
292 * Copy of the original store message (as data fields in @e rd will
293 * point into it!).
294 */
295 const struct RecordStoreMessage *rsm;
296
297 /**
298 * Next zone monitor that still needs to be notified about this PUT.
299 */
300 struct ZoneMonitor *zm_pos;
301
302 /**
303 * Label nicely canonicalized (lower case).
304 */
305 char *conv_name;
306};
307
308
309/**
310 * Entry in list of cached nick resolutions.
311 */
312struct NickCache
313{
314 /**
315 * Zone the cache entry is for.
316 */
317 struct GNUNET_IDENTITY_PrivateKey zone;
318
319 /**
320 * Cached record data.
321 */
322 struct GNUNET_GNSRECORD_Data *rd;
323
324 /**
325 * Timestamp when this cache entry was used last.
326 */
327 struct GNUNET_TIME_Absolute last_used;
328};
329
330
331/**
332 * We cache nick records to reduce DB load.
333 */
334static struct NickCache nick_cache[NC_SIZE];
335
336/**
337 * Public key of all zeros.
338 */
339static const struct GNUNET_IDENTITY_PrivateKey zero;
340
341/**
342 * Configuration handle.
343 */
344static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
345
346/**
347 * Handle to the statistics service
348 */
349static struct GNUNET_STATISTICS_Handle *statistics;
350
351/**
352 * Namecache handle.
353 */
354static struct GNUNET_NAMECACHE_Handle *namecache;
355
356/**
357 * Database handle
358 */
359static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
360
361/**
362 * Name of the database plugin
363 */
364static char *db_lib_name;
365
366/**
367 * Head of cop DLL.
368 */
369static struct CacheOperation *cop_head;
370
371/**
372 * Tail of cop DLL.
373 */
374static struct CacheOperation *cop_tail;
375
376/**
377 * First active zone monitor.
378 */
379static struct ZoneMonitor *monitor_head;
380
381/**
382 * Last active zone monitor.
383 */
384static struct ZoneMonitor *monitor_tail;
385
386/**
387 * Head of DLL of monitor-blocked store activities.
388 */
389static struct StoreActivity *sa_head;
390
391/**
392 * Tail of DLL of monitor-blocked store activities.
393 */
394static struct StoreActivity *sa_tail;
395
396/**
397 * Notification context shared by all monitors.
398 */
399static struct GNUNET_NotificationContext *monitor_nc;
400
401/**
402 * Optimize block insertion by caching map of private keys to
403 * public keys in memory?
404 */
405static int cache_keys;
406
407/**
408 * Use the namecache? Doing so creates additional cryptographic
409 * operations whenever we touch a record.
410 */
411static int disable_namecache;
412
413
414/**
415 * Task run during shutdown.
416 *
417 * @param cls unused
418 */
419static void
420cleanup_task (void *cls)
421{
422 struct CacheOperation *cop;
423
424 (void) cls;
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
426 while (NULL != (cop = cop_head))
427 {
428 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
429 "Aborting incomplete namecache operation\n");
430 GNUNET_NAMECACHE_cancel (cop->qe);
431 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
432 GNUNET_free (cop);
433 }
434 if (NULL != namecache)
435 {
436 GNUNET_NAMECACHE_disconnect (namecache);
437 namecache = NULL;
438 }
439 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
440 GNUNET_free (db_lib_name);
441 db_lib_name = NULL;
442 if (NULL != monitor_nc)
443 {
444 GNUNET_notification_context_destroy (monitor_nc);
445 monitor_nc = NULL;
446 }
447 if (NULL != statistics)
448 {
449 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
450 statistics = NULL;
451 }
452}
453
454
455/**
456 * Release memory used by @a sa.
457 *
458 * @param sa activity to free
459 */
460static void
461free_store_activity (struct StoreActivity *sa)
462{
463 GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa);
464 GNUNET_free (sa->conv_name);
465 GNUNET_free (sa);
466}
467
468
469/**
470 * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT
471 * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
472 * record, which (if found) is then copied to @a cls for future use.
473 *
474 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
475 * @param seq sequence number of the record, MUST NOT BE ZERO
476 * @param private_key the private key of the zone (unused)
477 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
478 * @param rd_count number of records in @a rd
479 * @param rd records stored under @a label in the zone
480 */
481static void
482lookup_nick_it (void *cls,
483 uint64_t seq,
484 const struct GNUNET_IDENTITY_PrivateKey *private_key,
485 const char *label,
486 unsigned int rd_count,
487 const struct GNUNET_GNSRECORD_Data *rd)
488{
489 struct GNUNET_GNSRECORD_Data **res = cls;
490
491 (void) private_key;
492 GNUNET_assert (0 != seq);
493 if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
494 {
495 GNUNET_break (0);
496 return;
497 }
498 for (unsigned int c = 0; c < rd_count; c++)
499 {
500 if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
501 {
502 (*res) =
503 GNUNET_malloc (rd[c].data_size + sizeof(struct GNUNET_GNSRECORD_Data));
504 (*res)->data = &(*res)[1];
505 GNUNET_memcpy ((void *) (*res)->data, rd[c].data, rd[c].data_size);
506 (*res)->data_size = rd[c].data_size;
507 (*res)->expiration_time = rd[c].expiration_time;
508 (*res)->flags = rd[c].flags;
509 (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
510 return;
511 }
512 }
513 (*res) = NULL;
514}
515
516
517/**
518 * Add entry to the cache for @a zone and @a nick
519 *
520 * @param zone zone key to cache under
521 * @param nick nick entry to cache
522 */
523static void
524cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone,
525 const struct GNUNET_GNSRECORD_Data *nick)
526{
527 struct NickCache *oldest;
528
529 oldest = NULL;
530 for (unsigned int i = 0; i < NC_SIZE; i++)
531 {
532 struct NickCache *pos = &nick_cache[i];
533
534 if ((NULL == oldest) ||
535 (oldest->last_used.abs_value_us > pos->last_used.abs_value_us))
536 oldest = pos;
537 if (0 == GNUNET_memcmp (zone, &pos->zone))
538 {
539 oldest = pos;
540 break;
541 }
542 }
543 GNUNET_free (oldest->rd);
544 oldest->zone = *zone;
545 if (NULL != nick)
546 {
547 oldest->rd = GNUNET_malloc (sizeof(*nick) + nick->data_size);
548 *oldest->rd = *nick;
549 oldest->rd->data = &oldest->rd[1];
550 memcpy (&oldest->rd[1], nick->data, nick->data_size);
551 }
552 else
553 {
554 oldest->rd = NULL;
555 }
556 oldest->last_used = GNUNET_TIME_absolute_get ();
557}
558
559
560/**
561 * Return the NICK record for the zone (if it exists).
562 *
563 * @param zone private key for the zone to look for nick
564 * @return NULL if no NICK record was found
565 */
566static struct GNUNET_GNSRECORD_Data *
567get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone)
568{
569 struct GNUNET_IDENTITY_PublicKey pub;
570 struct GNUNET_GNSRECORD_Data *nick;
571 int res;
572
573 /* check cache first */
574 for (unsigned int i = 0; i < NC_SIZE; i++)
575 {
576 struct NickCache *pos = &nick_cache[i];
577 if ((NULL != pos->rd) && (0 == GNUNET_memcmp (zone, &pos->zone)))
578 {
579 if (NULL == pos->rd)
580 return NULL;
581 nick = GNUNET_malloc (sizeof(*nick) + pos->rd->data_size);
582 *nick = *pos->rd;
583 nick->data = &nick[1];
584 memcpy (&nick[1], pos->rd->data, pos->rd->data_size);
585 pos->last_used = GNUNET_TIME_absolute_get ();
586 return nick;
587 }
588 }
589
590 nick = NULL;
591 res = GSN_database->lookup_records (GSN_database->cls,
592 zone,
593 GNUNET_GNS_EMPTY_LABEL_AT,
594 &lookup_nick_it,
595 &nick);
596 if ((GNUNET_OK != res) || (NULL == nick))
597 {
598#if ! defined(GNUNET_CULL_LOGGING)
599 static int do_log = GNUNET_LOG_CALL_STATUS;
600
601 if (0 == do_log)
602 do_log = GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_DEBUG,
603 "namestore",
604 __FILE__,
605 __FUNCTION__,
606 __LINE__);
607 if (1 == do_log)
608 {
609 GNUNET_IDENTITY_key_get_public (zone, &pub);
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
611 "No nick name set for zone `%s'\n",
612 GNUNET_GNSRECORD_z2s (&pub));
613 }
614#endif
615 /* update cache */
616 cache_nick (zone, NULL);
617 return NULL;
618 }
619
620 /* update cache */
621 cache_nick (zone, nick);
622 return nick;
623}
624
625
626/**
627 * Merge the nick record @a nick_rd with the rest of the
628 * record set given in @a rd2. Store the result in @a rdc_res
629 * and @a rd_res. The @a nick_rd's expiration time is set to
630 * the maximum expiration time of all of the records in @a rd2.
631 *
632 * @param nick_rd the nick record to integrate
633 * @param rd2_length length of the @a rd2 array
634 * @param rd2 array of records
635 * @param rdc_res[out] length of the resulting @a rd_res array
636 * @param rd_res[out] set to an array of records,
637 * including @a nick_rd and @a rd2;
638 * all of the variable-size 'data' fields in @a rd2 are
639 * allocated in the same chunk of memory!
640 */
641static void
642merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
643 unsigned int rd2_length,
644 const struct GNUNET_GNSRECORD_Data *rd2,
645 unsigned int *rdc_res,
646 struct GNUNET_GNSRECORD_Data **rd_res)
647{
648 uint64_t latest_expiration;
649 size_t req;
650 char *data;
651 size_t data_offset;
652 struct GNUNET_GNSRECORD_Data *target;
653
654 (*rdc_res) = 1 + rd2_length;
655 if (0 == 1 + rd2_length)
656 {
657 GNUNET_break (0);
658 (*rd_res) = NULL;
659 return;
660 }
661 req = sizeof(struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
662 for (unsigned int i = 0; i < rd2_length; i++)
663 {
664 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
665
666 if (req + sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
667 {
668 GNUNET_break (0);
669 (*rd_res) = NULL;
670 return;
671 }
672 req += sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size;
673 }
674 target = GNUNET_malloc (req);
675 (*rd_res) = target;
676 data = (char *) &target[1 + rd2_length];
677 data_offset = 0;
678 latest_expiration = 0;
679 for (unsigned int i = 0; i < rd2_length; i++)
680 {
681 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
682
683 if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
684 {
685 if ((GNUNET_TIME_absolute_get ().abs_value_us + orig->expiration_time) >
686 latest_expiration)
687 latest_expiration = orig->expiration_time;
688 }
689 else if (orig->expiration_time > latest_expiration)
690 latest_expiration = orig->expiration_time;
691 target[i] = *orig;
692 target[i].data = (void *) &data[data_offset];
693 GNUNET_memcpy (&data[data_offset], orig->data, orig->data_size);
694 data_offset += orig->data_size;
695 }
696 /* append nick */
697 target[rd2_length] = *nick_rd;
698 /* Mark as supplemental */
699 target[rd2_length].flags = nick_rd->flags | GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
700 target[rd2_length].expiration_time = latest_expiration;
701 target[rd2_length].data = (void *) &data[data_offset];
702 GNUNET_memcpy (&data[data_offset], nick_rd->data, nick_rd->data_size);
703 data_offset += nick_rd->data_size;
704 GNUNET_assert (req == (sizeof(struct GNUNET_GNSRECORD_Data)) * (*rdc_res)
705 + data_offset);
706}
707
708
709/**
710 * Generate a `struct LookupNameResponseMessage` and send it to the
711 * given client using the given notification context.
712 *
713 * @param nc client to unicast to
714 * @param request_id request ID to use
715 * @param zone_key zone key of the zone
716 * @param name name
717 * @param rd_count number of records in @a rd
718 * @param rd array of records
719 */
720static void
721send_lookup_response (struct NamestoreClient *nc,
722 uint32_t request_id,
723 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
724 const char *name,
725 unsigned int rd_count,
726 const struct GNUNET_GNSRECORD_Data *rd)
727{
728 struct GNUNET_MQ_Envelope *env;
729 struct RecordResultMessage *zir_msg;
730 struct GNUNET_GNSRECORD_Data *nick;
731 struct GNUNET_GNSRECORD_Data *res;
732 unsigned int res_count;
733 size_t name_len;
734 ssize_t rd_ser_len;
735 char *name_tmp;
736 char *rd_ser;
737
738 nick = get_nick_record (zone_key);
739 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
740
741 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
742 {
743 nick->flags =
744 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
745 merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
746 }
747 else
748 {
749 res_count = rd_count;
750 res = (struct GNUNET_GNSRECORD_Data *) rd;
751 }
752 if (NULL != nick)
753 GNUNET_free (nick);
754
755 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res));
756
757
758 name_len = strlen (name) + 1;
759 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
760 if (rd_ser_len < 0)
761 {
762 if (rd != res)
763 GNUNET_free (res);
764 GNUNET_break (0);
765 GNUNET_SERVICE_client_drop (nc->client);
766 return;
767 }
768 if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg))
769 {
770 if (rd != res)
771 GNUNET_free (res);
772 GNUNET_break (0);
773 GNUNET_SERVICE_client_drop (nc->client);
774 return;
775 }
776 env = GNUNET_MQ_msg_extra (zir_msg,
777 name_len + rd_ser_len,
778 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
779 zir_msg->gns_header.r_id = htonl (request_id);
780 zir_msg->name_len = htons (name_len);
781 zir_msg->rd_count = htons (res_count);
782 zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
783 zir_msg->private_key = *zone_key;
784 name_tmp = (char *) &zir_msg[1];
785 GNUNET_memcpy (name_tmp, name, name_len);
786 rd_ser = &name_tmp[name_len];
787 GNUNET_assert (
788 rd_ser_len ==
789 GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser));
790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791 "Sending RECORD_RESULT message with %u records\n",
792 res_count);
793 GNUNET_STATISTICS_update (statistics,
794 "Record sets sent to clients",
795 1,
796 GNUNET_NO);
797 GNUNET_MQ_send (nc->mq, env);
798 if (rd != res)
799 GNUNET_free (res);
800}
801
802
803/**
804 * Send response to the store request to the client.
805 *
806 * @param client client to talk to
807 * @param res status of the operation
808 * @param rid client's request ID
809 */
810static void
811send_store_response (struct NamestoreClient *nc, int res, uint32_t rid)
812{
813 struct GNUNET_MQ_Envelope *env;
814 struct RecordStoreResponseMessage *rcr_msg;
815
816 GNUNET_assert (NULL != nc);
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
818 "Sending RECORD_STORE_RESPONSE message\n");
819 GNUNET_STATISTICS_update (statistics,
820 "Store requests completed",
821 1,
822 GNUNET_NO);
823 env = GNUNET_MQ_msg (rcr_msg,
824 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
825 rcr_msg->gns_header.r_id = htonl (rid);
826 rcr_msg->op_result = htonl (res);
827 GNUNET_MQ_send (nc->mq, env);
828}
829
830
831/**
832 * Function called once we are done with the zone iteration and
833 * allow the zone iteration client to send us more messages.
834 *
835 * @param zi zone iteration we are processing
836 */
837static void
838zone_iteration_done_client_continue (struct ZoneIteration *zi)
839{
840 struct GNUNET_MQ_Envelope *env;
841 struct GNUNET_NAMESTORE_Header *em;
842
843 GNUNET_SERVICE_client_continue (zi->nc->client);
844 if (! zi->send_end)
845 return;
846 /* send empty response to indicate end of list */
847 env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
848 em->r_id = htonl (zi->request_id);
849 GNUNET_MQ_send (zi->nc->mq, env);
850
851 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi);
852 GNUNET_free (zi);
853}
854
855
856/**
857 * Cache operation complete, clean up.
858 *
859 * @param cls the `struct CacheOperation`
860 * @param success success
861 * @param emsg error messages
862 */
863static void
864finish_cache_operation (void *cls, int32_t success, const char *emsg)
865{
866 struct CacheOperation *cop = cls;
867 struct ZoneIteration *zi;
868
869 if (NULL != emsg)
870 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
871 _ ("Failed to replicate block in namecache: %s\n"),
872 emsg);
873 else
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
875 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
876 if (NULL != cop->nc)
877 send_store_response (cop->nc, success, cop->rid);
878 if (NULL != (zi = cop->zi))
879 {
880 zi->cache_ops--;
881 if (0 == zi->cache_ops)
882 {
883 /* unchoke zone iteration, cache has caught up */
884 zone_iteration_done_client_continue (zi);
885 }
886 }
887 GNUNET_free (cop);
888}
889
890
891/**
892 * We just touched the plaintext information about a name in our zone;
893 * refresh the corresponding (encrypted) block in the namecache.
894 *
895 * @param nc client responsible for the request, can be NULL
896 * @param zi zone iteration response for the request, can be NULL
897 * @param rid request ID of the client
898 * @param zone_key private key of the zone
899 * @param name label for the records
900 * @param rd_count number of records
901 * @param rd records stored under the given @a name
902 */
903static void
904refresh_block (struct NamestoreClient *nc,
905 struct ZoneIteration *zi,
906 uint32_t rid,
907 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
908 const char *name,
909 unsigned int rd_count,
910 const struct GNUNET_GNSRECORD_Data *rd)
911{
912 struct GNUNET_GNSRECORD_Block *block;
913 struct CacheOperation *cop;
914 struct GNUNET_IDENTITY_PublicKey pkey;
915 struct GNUNET_GNSRECORD_Data *nick;
916 struct GNUNET_GNSRECORD_Data *res;
917 unsigned int res_count;
918 struct GNUNET_TIME_Absolute exp_time;
919
920 nick = get_nick_record (zone_key);
921 res_count = rd_count;
922 res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
923 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
924 {
925 nick->flags =
926 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
927 merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
928 }
929 if (NULL != nick)
930 GNUNET_free (nick);
931 if (0 == res_count)
932 {
933 if (NULL != nc)
934 send_store_response (nc, GNUNET_OK, rid);
935 if (rd != res)
936 GNUNET_free (res);
937 return; /* no data, no need to update cache */
938 }
939 if (GNUNET_YES == disable_namecache)
940 {
941 GNUNET_STATISTICS_update (statistics,
942 "Namecache updates skipped (NC disabled)",
943 1,
944 GNUNET_NO);
945 if (NULL != nc)
946 send_store_response (nc, GNUNET_OK, rid);
947 if (rd != res)
948 GNUNET_free (res);
949 return;
950 }
951 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res);
952 if (cache_keys)
953 block =
954 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, res, res_count);
955 else
956 block =
957 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, res, res_count);
958 GNUNET_assert (NULL != block);
959 GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
960 GNUNET_log (
961 GNUNET_ERROR_TYPE_DEBUG,
962 "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
963 name,
964 res_count,
965 GNUNET_STRINGS_absolute_time_to_string (exp_time),
966 GNUNET_GNSRECORD_z2s (&pkey));
967 GNUNET_STATISTICS_update (statistics,
968 "Namecache updates pushed",
969 1,
970 GNUNET_NO);
971 cop = GNUNET_new (struct CacheOperation);
972 cop->nc = nc;
973 cop->zi = zi;
974 if (NULL != zi)
975 zi->cache_ops++;
976 cop->rid = rid;
977 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
978 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
979 block,
980 &finish_cache_operation,
981 cop);
982 GNUNET_free (block);
983 if (rd != res)
984 GNUNET_free (res);
985}
986
987
988/**
989 * Print a warning that one of our monitors is no longer reacting.
990 *
991 * @param cls a `struct ZoneMonitor` to warn about
992 */
993static void
994warn_monitor_slow (void *cls)
995{
996 struct ZoneMonitor *zm = cls;
997
998 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
999 "No response from monitor since %s\n",
1000 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
1001 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1002 &warn_monitor_slow,
1003 zm);
1004}
1005
1006
1007/**
1008 * Continue processing the @a sa.
1009 *
1010 * @param sa store activity to process
1011 */
1012static void
1013continue_store_activity (struct StoreActivity *sa)
1014{
1015 const struct RecordStoreMessage *rp_msg = sa->rsm;
1016 unsigned int rd_count;
1017 size_t name_len;
1018 size_t rd_ser_len;
1019 uint32_t rid;
1020 const char *name_tmp;
1021 const char *rd_ser;
1022
1023 rid = ntohl (rp_msg->gns_header.r_id);
1024 name_len = ntohs (rp_msg->name_len);
1025 rd_count = ntohs (rp_msg->rd_count);
1026 rd_ser_len = ntohs (rp_msg->rd_len);
1027 name_tmp = (const char *) &rp_msg[1];
1028 rd_ser = &name_tmp[name_len];
1029 {
1030 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1031
1032 /* We did this before, must succeed again */
1033 GNUNET_assert (
1034 GNUNET_OK ==
1035 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd));
1036
1037 for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos)
1038 {
1039 if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) &&
1040 (0 != GNUNET_memcmp (&zm->zone, &zero)))
1041 {
1042 sa->zm_pos = zm->next; /* not interesting to this monitor */
1043 continue;
1044 }
1045 if (zm->limit == zm->iteration_cnt)
1046 {
1047 zm->sa_waiting = GNUNET_YES;
1048 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1049 if (NULL != zm->sa_wait_warning)
1050 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1051 zm->sa_wait_warning =
1052 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1053 &warn_monitor_slow,
1054 zm);
1055 return; /* blocked on zone monitor */
1056 }
1057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1058 "Notifying monitor about changes under label `%s'\n",
1059 sa->conv_name);
1060 zm->limit--;
1061 send_lookup_response (zm->nc,
1062 0,
1063 &rp_msg->private_key,
1064 sa->conv_name,
1065 rd_count,
1066 rd);
1067 sa->zm_pos = zm->next;
1068 }
1069 /* great, done with the monitors, unpack (again) for refresh_block operation */
1070 refresh_block (sa->nc,
1071 NULL,
1072 rid,
1073 &rp_msg->private_key,
1074 sa->conv_name,
1075 rd_count,
1076 rd);
1077 }
1078 GNUNET_SERVICE_client_continue (sa->nc->client);
1079 free_store_activity (sa);
1080}
1081
1082
1083/**
1084 * Called whenever a client is disconnected.
1085 * Frees our resources associated with that client.
1086 *
1087 * @param cls closure
1088 * @param client identification of the client
1089 * @param app_ctx the `struct NamestoreClient` of @a client
1090 */
1091static void
1092client_disconnect_cb (void *cls,
1093 struct GNUNET_SERVICE_Client *client,
1094 void *app_ctx)
1095{
1096 struct NamestoreClient *nc = app_ctx;
1097 struct ZoneIteration *no;
1098 struct CacheOperation *cop;
1099
1100 (void) cls;
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1102 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1103 {
1104 struct StoreActivity *san;
1105
1106 if (nc != zm->nc)
1107 continue;
1108 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm);
1109 if (NULL != zm->task)
1110 {
1111 GNUNET_SCHEDULER_cancel (zm->task);
1112 zm->task = NULL;
1113 }
1114 if (NULL != zm->sa_wait_warning)
1115 {
1116 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1117 zm->sa_wait_warning = NULL;
1118 }
1119 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1120 {
1121 san = sa->next;
1122 if (zm == sa->zm_pos)
1123 {
1124 sa->zm_pos = zm->next;
1125 /* this may free sa */
1126 continue_store_activity (sa);
1127 }
1128 }
1129 GNUNET_free (zm);
1130 break;
1131 }
1132 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1133 {
1134 if (sa->nc == nc)
1135 {
1136 /* this may free sa */
1137 free_store_activity (sa);
1138 break; /* there can only be one per nc */
1139 }
1140 }
1141 while (NULL != (no = nc->op_head))
1142 {
1143 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
1144 GNUNET_free (no);
1145 }
1146 for (cop = cop_head; NULL != cop; cop = cop->next)
1147 if (nc == cop->nc)
1148 cop->nc = NULL;
1149 GNUNET_free (nc);
1150}
1151
1152
1153/**
1154 * Add a client to our list of active clients.
1155 *
1156 * @param cls NULL
1157 * @param client client to add
1158 * @param mq message queue for @a client
1159 * @return internal namestore client structure for this client
1160 */
1161static void *
1162client_connect_cb (void *cls,
1163 struct GNUNET_SERVICE_Client *client,
1164 struct GNUNET_MQ_Handle *mq)
1165{
1166 struct NamestoreClient *nc;
1167
1168 (void) cls;
1169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1170 nc = GNUNET_new (struct NamestoreClient);
1171 nc->client = client;
1172 nc->mq = mq;
1173 return nc;
1174}
1175
1176
1177/**
1178 * Closure for #lookup_it().
1179 */
1180struct RecordLookupContext
1181{
1182 /**
1183 * FIXME.
1184 */
1185 const char *label;
1186
1187 /**
1188 * FIXME.
1189 */
1190 char *res_rd;
1191
1192 /**
1193 * FIXME.
1194 */
1195 struct GNUNET_GNSRECORD_Data *nick;
1196
1197 /**
1198 * FIXME.
1199 */
1200 int found;
1201
1202 /**
1203 * FIXME.
1204 */
1205 unsigned int res_rd_count;
1206
1207 /**
1208 * FIXME.
1209 */
1210 ssize_t rd_ser_len;
1211};
1212
1213
1214/**
1215 * Function called by the namestore plugin when we are trying to lookup
1216 * a record as part of #handle_record_lookup(). Merges all results into
1217 * the context.
1218 *
1219 * @param cls closure with a `struct RecordLookupContext`
1220 * @param seq unique serial number of the record, MUST NOT BE ZERO
1221 * @param zone_key private key of the zone
1222 * @param label name that is being mapped (at most 255 characters long)
1223 * @param rd_count number of entries in @a rd array
1224 * @param rd array of records with data to store
1225 */
1226static void
1227lookup_it (void *cls,
1228 uint64_t seq,
1229 const struct GNUNET_IDENTITY_PrivateKey *private_key,
1230 const char *label,
1231 unsigned int rd_count,
1232 const struct GNUNET_GNSRECORD_Data *rd)
1233{
1234 struct RecordLookupContext *rlc = cls;
1235
1236 (void) private_key;
1237 GNUNET_assert (0 != seq);
1238 if (0 != strcmp (label, rlc->label))
1239 return;
1240 rlc->found = GNUNET_YES;
1241 if (0 == rd_count)
1242 {
1243 rlc->rd_ser_len = 0;
1244 rlc->res_rd_count = 0;
1245 rlc->res_rd = NULL;
1246 return;
1247 }
1248 if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)))
1249 {
1250 /* Merge */
1251 struct GNUNET_GNSRECORD_Data *rd_res;
1252 unsigned int rdc_res;
1253
1254 rd_res = NULL;
1255 rdc_res = 0;
1256 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE)
1257 ^ GNUNET_GNSRECORD_RF_PRIVATE;
1258 merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res);
1259 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res);
1260 if (rlc->rd_ser_len < 0)
1261 {
1262 GNUNET_break (0);
1263 GNUNET_free (rd_res);
1264 rlc->found = GNUNET_NO;
1265 rlc->rd_ser_len = 0;
1266 return;
1267 }
1268 rlc->res_rd_count = rdc_res;
1269 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1270 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res,
1271 rd_res,
1272 rlc->rd_ser_len,
1273 rlc->res_rd))
1274 {
1275 GNUNET_break (0);
1276 GNUNET_free (rlc->res_rd);
1277 rlc->res_rd = NULL;
1278 rlc->res_rd_count = 0;
1279 rlc->rd_ser_len = 0;
1280 GNUNET_free (rd_res);
1281 rlc->found = GNUNET_NO;
1282 return;
1283 }
1284 GNUNET_free (rd_res);
1285 GNUNET_free (rlc->nick);
1286 rlc->nick = NULL;
1287 }
1288 else
1289 {
1290 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1291 if (rlc->rd_ser_len < 0)
1292 {
1293 GNUNET_break (0);
1294 rlc->found = GNUNET_NO;
1295 rlc->rd_ser_len = 0;
1296 return;
1297 }
1298 rlc->res_rd_count = rd_count;
1299 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1300 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count,
1301 rd,
1302 rlc->rd_ser_len,
1303 rlc->res_rd))
1304 {
1305 GNUNET_break (0);
1306 GNUNET_free (rlc->res_rd);
1307 rlc->res_rd = NULL;
1308 rlc->res_rd_count = 0;
1309 rlc->rd_ser_len = 0;
1310 rlc->found = GNUNET_NO;
1311 return;
1312 }
1313 }
1314}
1315
1316
1317/**
1318 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1319 *
1320 * @param cls client sending the message
1321 * @param ll_msg message of type `struct LabelLookupMessage`
1322 * @return #GNUNET_OK if @a ll_msg is well-formed
1323 */
1324static int
1325check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1326{
1327 uint32_t name_len;
1328 size_t src_size;
1329
1330 (void) cls;
1331 name_len = ntohl (ll_msg->label_len);
1332 src_size = ntohs (ll_msg->gns_header.header.size);
1333 if (name_len != src_size - sizeof(struct LabelLookupMessage))
1334 {
1335 GNUNET_break (0);
1336 return GNUNET_SYSERR;
1337 }
1338 GNUNET_MQ_check_zero_termination (ll_msg);
1339 return GNUNET_OK;
1340}
1341
1342
1343/**
1344 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1345 *
1346 * @param cls client sending the message
1347 * @param ll_msg message of type `struct LabelLookupMessage`
1348 */
1349static void
1350handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1351{
1352 struct NamestoreClient *nc = cls;
1353 struct GNUNET_MQ_Envelope *env;
1354 struct LabelLookupResponseMessage *llr_msg;
1355 struct RecordLookupContext rlc;
1356 const char *name_tmp;
1357 char *res_name;
1358 char *conv_name;
1359 uint32_t name_len;
1360 int res;
1361
1362 name_len = ntohl (ll_msg->label_len);
1363 name_tmp = (const char *) &ll_msg[1];
1364 GNUNET_SERVICE_client_continue (nc->client);
1365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1367 name_tmp);
1368
1369 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1370 if (NULL == conv_name)
1371 {
1372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1373 "Error converting name `%s'\n",
1374 name_tmp);
1375 GNUNET_SERVICE_client_drop (nc->client);
1376 return;
1377 }
1378 rlc.label = conv_name;
1379 rlc.found = GNUNET_NO;
1380 rlc.res_rd_count = 0;
1381 rlc.res_rd = NULL;
1382 rlc.rd_ser_len = 0;
1383 rlc.nick = get_nick_record (&ll_msg->zone);
1384 res = GSN_database->lookup_records (GSN_database->cls,
1385 &ll_msg->zone,
1386 conv_name,
1387 &lookup_it,
1388 &rlc);
1389 GNUNET_free (conv_name);
1390 env =
1391 GNUNET_MQ_msg_extra (llr_msg,
1392 name_len + rlc.rd_ser_len,
1393 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1394 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1395 llr_msg->private_key = ll_msg->zone;
1396 llr_msg->name_len = htons (name_len);
1397 llr_msg->rd_count = htons (rlc.res_rd_count);
1398 llr_msg->rd_len = htons (rlc.rd_ser_len);
1399 res_name = (char *) &llr_msg[1];
1400 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1401 llr_msg->found = ntohs (GNUNET_YES);
1402 else
1403 llr_msg->found = ntohs (GNUNET_NO);
1404 GNUNET_memcpy (&llr_msg[1], name_tmp, name_len);
1405 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1406 GNUNET_MQ_send (nc->mq, env);
1407 GNUNET_free (rlc.res_rd);
1408}
1409
1410
1411/**
1412 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1413 *
1414 * @param cls client sending the message
1415 * @param rp_msg message of type `struct RecordStoreMessage`
1416 * @return #GNUNET_OK if @a rp_msg is well-formed
1417 */
1418static int
1419check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1420{
1421 size_t name_len;
1422 size_t msg_size;
1423 size_t msg_size_exp;
1424 size_t rd_ser_len;
1425 const char *name_tmp;
1426
1427 (void) cls;
1428 name_len = ntohs (rp_msg->name_len);
1429 msg_size = ntohs (rp_msg->gns_header.header.size);
1430 rd_ser_len = ntohs (rp_msg->rd_len);
1431 msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len;
1432 if (msg_size != msg_size_exp)
1433 {
1434 GNUNET_break (0);
1435 return GNUNET_SYSERR;
1436 }
1437 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1438 {
1439 GNUNET_break (0);
1440 return GNUNET_SYSERR;
1441 }
1442 name_tmp = (const char *) &rp_msg[1];
1443 if ('\0' != name_tmp[name_len - 1])
1444 {
1445 GNUNET_break (0);
1446 return GNUNET_SYSERR;
1447 }
1448 return GNUNET_OK;
1449}
1450
1451
1452/**
1453 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1454 *
1455 * @param cls client sending the message
1456 * @param rp_msg message of type `struct RecordStoreMessage`
1457 */
1458static void
1459handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1460{
1461 struct NamestoreClient *nc = cls;
1462 size_t name_len;
1463 size_t rd_ser_len;
1464 uint32_t rid;
1465 const char *name_tmp;
1466 char *conv_name;
1467 const char *rd_ser;
1468 unsigned int rd_count;
1469 int res;
1470 struct StoreActivity *sa;
1471
1472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1473 "Received NAMESTORE_RECORD_STORE message\n");
1474 rid = ntohl (rp_msg->gns_header.r_id);
1475 name_len = ntohs (rp_msg->name_len);
1476 rd_count = ntohs (rp_msg->rd_count);
1477 rd_ser_len = ntohs (rp_msg->rd_len);
1478 GNUNET_break (0 == ntohs (rp_msg->reserved));
1479 name_tmp = (const char *) &rp_msg[1];
1480 rd_ser = &name_tmp[name_len];
1481 {
1482 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1483
1484 if (GNUNET_OK !=
1485 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1486 {
1487 GNUNET_break (0);
1488 GNUNET_SERVICE_client_drop (nc->client);
1489 return;
1490 }
1491
1492 /* Extracting and converting private key */
1493 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1494 if (NULL == conv_name)
1495 {
1496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1497 "Error converting name `%s'\n",
1498 name_tmp);
1499 GNUNET_SERVICE_client_drop (nc->client);
1500 return;
1501 }
1502 GNUNET_STATISTICS_update (statistics,
1503 "Well-formed store requests received",
1504 1,
1505 GNUNET_NO);
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "Creating %u records for name `%s'\n",
1508 (unsigned int) rd_count,
1509 conv_name);
1510 if ((0 == rd_count) &&
1511 (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1512 &rp_msg->private_key,
1513 conv_name,
1514 NULL,
1515 0)))
1516 {
1517 /* This name does not exist, so cannot be removed */
1518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1519 "Name `%s' does not exist, no deletion required\n",
1520 conv_name);
1521 res = GNUNET_NO;
1522 }
1523 else
1524 {
1525 /* remove "NICK" records, unless this is for the
1526 #GNUNET_GNS_EMPTY_LABEL_AT label */
1527 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1528 unsigned int rd_clean_off;
1529 int have_nick;
1530
1531 rd_clean_off = 0;
1532 have_nick = GNUNET_NO;
1533 for (unsigned int i = 0; i < rd_count; i++)
1534 {
1535 rd_clean[rd_clean_off] = rd[i];
1536 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1537 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1538 rd_clean_off++;
1539
1540 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1541 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
1542 {
1543 cache_nick (&rp_msg->private_key, &rd[i]);
1544 have_nick = GNUNET_YES;
1545 }
1546 }
1547 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1548 (GNUNET_NO == have_nick))
1549 {
1550 /* remove nick record from cache, in case we have one there */
1551 cache_nick (&rp_msg->private_key, NULL);
1552 }
1553 res = GSN_database->store_records (GSN_database->cls,
1554 &rp_msg->private_key,
1555 conv_name,
1556 rd_clean_off,
1557 rd_clean);
1558 }
1559
1560 if (GNUNET_OK != res)
1561 {
1562 /* store not successful, not need to tell monitors */
1563 send_store_response (nc, res, rid);
1564 GNUNET_SERVICE_client_continue (nc->client);
1565 GNUNET_free (conv_name);
1566 return;
1567 }
1568
1569 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1570 + ntohs (rp_msg->gns_header.header.size));
1571 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1572 sa->nc = nc;
1573 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1574 GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size));
1575 sa->zm_pos = monitor_head;
1576 sa->conv_name = conv_name;
1577 continue_store_activity (sa);
1578 }
1579}
1580
1581
1582/**
1583 * Context for record remove operations passed from #handle_zone_to_name to
1584 * #handle_zone_to_name_it as closure
1585 */
1586struct ZoneToNameCtx
1587{
1588 /**
1589 * Namestore client
1590 */
1591 struct NamestoreClient *nc;
1592
1593 /**
1594 * Request id (to be used in the response to the client).
1595 */
1596 uint32_t rid;
1597
1598 /**
1599 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1600 * not finding a name for the zone still counts as a 'success' here,
1601 * as this field is about the success of executing the IPC protocol.
1602 */
1603 int success;
1604};
1605
1606
1607/**
1608 * Zone to name iterator
1609 *
1610 * @param cls struct ZoneToNameCtx *
1611 * @param seq sequence number of the record, MUST NOT BE ZERO
1612 * @param zone_key the zone key
1613 * @param name name
1614 * @param rd_count number of records in @a rd
1615 * @param rd record data
1616 */
1617static void
1618handle_zone_to_name_it (void *cls,
1619 uint64_t seq,
1620 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1621 const char *name,
1622 unsigned int rd_count,
1623 const struct GNUNET_GNSRECORD_Data *rd)
1624{
1625 struct ZoneToNameCtx *ztn_ctx = cls;
1626 struct GNUNET_MQ_Envelope *env;
1627 struct ZoneToNameResponseMessage *ztnr_msg;
1628 int16_t res;
1629 size_t name_len;
1630 ssize_t rd_ser_len;
1631 size_t msg_size;
1632 char *name_tmp;
1633 char *rd_tmp;
1634
1635 GNUNET_assert (0 != seq);
1636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1637 "Found result for zone-to-name lookup: `%s'\n",
1638 name);
1639 res = GNUNET_YES;
1640 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1641 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1642 if (rd_ser_len < 0)
1643 {
1644 GNUNET_break (0);
1645 ztn_ctx->success = GNUNET_SYSERR;
1646 return;
1647 }
1648 msg_size = sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1649 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1650 {
1651 GNUNET_break (0);
1652 ztn_ctx->success = GNUNET_SYSERR;
1653 return;
1654 }
1655 env =
1656 GNUNET_MQ_msg_extra (ztnr_msg,
1657 name_len + rd_ser_len,
1658 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1659 ztnr_msg->gns_header.header.size = htons (msg_size);
1660 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1661 ztnr_msg->res = htons (res);
1662 ztnr_msg->rd_len = htons (rd_ser_len);
1663 ztnr_msg->rd_count = htons (rd_count);
1664 ztnr_msg->name_len = htons (name_len);
1665 ztnr_msg->zone = *zone_key;
1666 name_tmp = (char *) &ztnr_msg[1];
1667 GNUNET_memcpy (name_tmp, name, name_len);
1668 rd_tmp = &name_tmp[name_len];
1669 GNUNET_assert (
1670 rd_ser_len ==
1671 GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
1672 ztn_ctx->success = GNUNET_OK;
1673 GNUNET_MQ_send (ztn_ctx->nc->mq, env);
1674}
1675
1676
1677/**
1678 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1679 *
1680 * @param cls client client sending the message
1681 * @param ztn_msg message of type 'struct ZoneToNameMessage'
1682 */
1683static void
1684handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
1685{
1686 struct NamestoreClient *nc = cls;
1687 struct ZoneToNameCtx ztn_ctx;
1688 struct GNUNET_MQ_Envelope *env;
1689 struct ZoneToNameResponseMessage *ztnr_msg;
1690
1691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
1692 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1693 ztn_ctx.nc = nc;
1694 ztn_ctx.success = GNUNET_NO;
1695 if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls,
1696 &ztn_msg->zone,
1697 &ztn_msg->value_zone,
1698 &handle_zone_to_name_it,
1699 &ztn_ctx))
1700 {
1701 /* internal error, hang up instead of signalling something
1702 that might be wrong */
1703 GNUNET_break (0);
1704 GNUNET_SERVICE_client_drop (nc->client);
1705 return;
1706 }
1707 if (GNUNET_NO == ztn_ctx.success)
1708 {
1709 /* no result found, send empty response */
1710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1711 "Found no result for zone-to-name lookup.\n");
1712 env = GNUNET_MQ_msg (ztnr_msg,
1713 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1714 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1715 ztnr_msg->res = htons (GNUNET_NO);
1716 GNUNET_MQ_send (nc->mq, env);
1717 }
1718 GNUNET_SERVICE_client_continue (nc->client);
1719}
1720
1721
1722/**
1723 * Context for record remove operations passed from
1724 * #run_zone_iteration_round to #zone_iterate_proc as closure
1725 */
1726struct ZoneIterationProcResult
1727{
1728 /**
1729 * The zone iteration handle
1730 */
1731 struct ZoneIteration *zi;
1732
1733 /**
1734 * Number of results left to be returned in this iteration.
1735 */
1736 uint64_t limit;
1737};
1738
1739
1740/**
1741 * Process results for zone iteration from database
1742 *
1743 * @param cls struct ZoneIterationProcResult
1744 * @param seq sequence number of the record, MUST NOT BE ZERO
1745 * @param zone_key the zone key
1746 * @param name name
1747 * @param rd_count number of records for this name
1748 * @param rd record data
1749 */
1750static void
1751zone_iterate_proc (void *cls,
1752 uint64_t seq,
1753 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1754 const char *name,
1755 unsigned int rd_count,
1756 const struct GNUNET_GNSRECORD_Data *rd)
1757{
1758 struct ZoneIterationProcResult *proc = cls;
1759 int do_refresh_block;
1760
1761 GNUNET_assert (0 != seq);
1762 if ((NULL == zone_key) && (NULL == name))
1763 {
1764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1765 return;
1766 }
1767 if ((NULL == zone_key) || (NULL == name))
1768 {
1769 /* what is this!? should never happen */
1770 GNUNET_break (0);
1771 return;
1772 }
1773 if (0 == proc->limit)
1774 {
1775 /* what is this!? should never happen */
1776 GNUNET_break (0);
1777 return;
1778 }
1779 proc->limit--;
1780 proc->zi->seq = seq;
1781 send_lookup_response (proc->zi->nc,
1782 proc->zi->request_id,
1783 zone_key,
1784 name,
1785 rd_count,
1786 rd);
1787
1788
1789 do_refresh_block = GNUNET_NO;
1790 for (unsigned int i = 0; i < rd_count; i++)
1791 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1792 {
1793 do_refresh_block = GNUNET_YES;
1794 break;
1795 }
1796 if (GNUNET_YES == do_refresh_block)
1797 refresh_block (NULL, proc->zi, 0, zone_key, name, rd_count, rd);
1798}
1799
1800
1801/**
1802 * Perform the next round of the zone iteration.
1803 *
1804 * @param zi zone iterator to process
1805 * @param limit number of results to return in one pass
1806 */
1807static void
1808run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
1809{
1810 struct ZoneIterationProcResult proc;
1811 struct GNUNET_TIME_Absolute start;
1812 struct GNUNET_TIME_Relative duration;
1813
1814 memset (&proc, 0, sizeof(proc));
1815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1816 "Asked to return up to %llu records at position %llu\n",
1817 (unsigned long long) limit,
1818 (unsigned long long) zi->seq);
1819 proc.zi = zi;
1820 proc.limit = limit;
1821 start = GNUNET_TIME_absolute_get ();
1822 GNUNET_break (GNUNET_SYSERR !=
1823 GSN_database->iterate_records (GSN_database->cls,
1824 (GNUNET_YES == GNUNET_is_zero (
1825 &zi->zone))
1826 ? NULL
1827 : &zi->zone,
1828 zi->seq,
1829 limit,
1830 &zone_iterate_proc,
1831 &proc));
1832 duration = GNUNET_TIME_absolute_get_duration (start);
1833 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
1834 GNUNET_STATISTICS_set (statistics,
1835 "NAMESTORE iteration delay (μs/record)",
1836 duration.rel_value_us,
1837 GNUNET_NO);
1838 if (0 == proc.limit)
1839 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1840 "Returned %llu results, more results available\n",
1841 (unsigned long long) limit);
1842 zi->send_end = (0 != proc.limit);
1843 if (0 == zi->cache_ops)
1844 zone_iteration_done_client_continue (zi);
1845}
1846
1847
1848/**
1849 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1850 *
1851 * @param cls the client sending the message
1852 * @param zis_msg message from the client
1853 */
1854static void
1855handle_iteration_start (void *cls,
1856 const struct ZoneIterationStartMessage *zis_msg)
1857{
1858 struct NamestoreClient *nc = cls;
1859 struct ZoneIteration *zi;
1860
1861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1862 "Received ZONE_ITERATION_START message\n");
1863 zi = GNUNET_new (struct ZoneIteration);
1864 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1865 zi->offset = 0;
1866 zi->nc = nc;
1867 zi->zone = zis_msg->zone;
1868
1869 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1870 run_zone_iteration_round (zi, 1);
1871}
1872
1873
1874/**
1875 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1876 *
1877 * @param cls the client sending the message
1878 * @param zis_msg message from the client
1879 */
1880static void
1881handle_iteration_stop (void *cls,
1882 const struct ZoneIterationStopMessage *zis_msg)
1883{
1884 struct NamestoreClient *nc = cls;
1885 struct ZoneIteration *zi;
1886 uint32_t rid;
1887
1888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1889 "Received ZONE_ITERATION_STOP message\n");
1890 rid = ntohl (zis_msg->gns_header.r_id);
1891 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1892 if (zi->request_id == rid)
1893 break;
1894 if (NULL == zi)
1895 {
1896 GNUNET_break (0);
1897 GNUNET_SERVICE_client_drop (nc->client);
1898 return;
1899 }
1900 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
1901 GNUNET_free (zi);
1902 GNUNET_SERVICE_client_continue (nc->client);
1903}
1904
1905
1906/**
1907 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
1908 *
1909 * @param cls the client sending the message
1910 * @param message message from the client
1911 */
1912static void
1913handle_iteration_next (void *cls,
1914 const struct ZoneIterationNextMessage *zis_msg)
1915{
1916 struct NamestoreClient *nc = cls;
1917 struct ZoneIteration *zi;
1918 uint32_t rid;
1919 uint64_t limit;
1920
1921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1922 "Received ZONE_ITERATION_NEXT message\n");
1923 GNUNET_STATISTICS_update (statistics,
1924 "Iteration NEXT messages received",
1925 1,
1926 GNUNET_NO);
1927 rid = ntohl (zis_msg->gns_header.r_id);
1928 limit = GNUNET_ntohll (zis_msg->limit);
1929 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1930 if (zi->request_id == rid)
1931 break;
1932 if (NULL == zi)
1933 {
1934 GNUNET_break (0);
1935 GNUNET_SERVICE_client_drop (nc->client);
1936 return;
1937 }
1938 run_zone_iteration_round (zi, limit);
1939}
1940
1941
1942/**
1943 * Function called when the monitor is ready for more data, and we
1944 * should thus unblock PUT operations that were blocked on the
1945 * monitor not being ready.
1946 */
1947static void
1948monitor_unblock (struct ZoneMonitor *zm)
1949{
1950 struct StoreActivity *sa = sa_head;
1951
1952 while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
1953 {
1954 struct StoreActivity *sn = sa->next;
1955
1956 if (sa->zm_pos == zm)
1957 continue_store_activity (sa);
1958 sa = sn;
1959 }
1960 if (zm->limit > zm->iteration_cnt)
1961 {
1962 zm->sa_waiting = GNUNET_NO;
1963 if (NULL != zm->sa_wait_warning)
1964 {
1965 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1966 zm->sa_wait_warning = NULL;
1967 }
1968 }
1969 else if (GNUNET_YES == zm->sa_waiting)
1970 {
1971 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1972 if (NULL != zm->sa_wait_warning)
1973 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1974 zm->sa_wait_warning =
1975 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1976 &warn_monitor_slow,
1977 zm);
1978 }
1979}
1980
1981
1982/**
1983 * Send 'sync' message to zone monitor, we're now in sync.
1984 *
1985 * @param zm monitor that is now in sync
1986 */
1987static void
1988monitor_sync (struct ZoneMonitor *zm)
1989{
1990 struct GNUNET_MQ_Envelope *env;
1991 struct GNUNET_MessageHeader *sync;
1992
1993 env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1994 GNUNET_MQ_send (zm->nc->mq, env);
1995 /* mark iteration done */
1996 zm->in_first_iteration = GNUNET_NO;
1997 zm->iteration_cnt = 0;
1998 if ((zm->limit > 0) && (zm->sa_waiting))
1999 monitor_unblock (zm);
2000}
2001
2002
2003/**
2004 * Obtain the next datum during the zone monitor's zone initial iteration.
2005 *
2006 * @param cls zone monitor that does its initial iteration
2007 */
2008static void
2009monitor_iteration_next (void *cls);
2010
2011
2012/**
2013 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2014 *
2015 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2016 * @param seq sequence number of the record, MUST NOT BE ZERO
2017 * @param zone_key zone key of the zone
2018 * @param name name
2019 * @param rd_count number of records in @a rd
2020 * @param rd array of records
2021 */
2022static void
2023monitor_iterate_cb (void *cls,
2024 uint64_t seq,
2025 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2026 const char *name,
2027 unsigned int rd_count,
2028 const struct GNUNET_GNSRECORD_Data *rd)
2029{
2030 struct ZoneMonitor *zm = cls;
2031
2032 GNUNET_assert (0 != seq);
2033 zm->seq = seq;
2034 GNUNET_assert (NULL != name);
2035 GNUNET_STATISTICS_update (statistics,
2036 "Monitor notifications sent",
2037 1,
2038 GNUNET_NO);
2039 zm->limit--;
2040 zm->iteration_cnt--;
2041 send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd);
2042 if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2043 {
2044 /* We are done with the current iteration batch, AND the
2045 client would right now accept more, so go again! */
2046 GNUNET_assert (NULL == zm->task);
2047 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2048 }
2049}
2050
2051
2052/**
2053 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2054 *
2055 * @param cls the client sending the message
2056 * @param zis_msg message from the client
2057 */
2058static void
2059handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg)
2060{
2061 struct NamestoreClient *nc = cls;
2062 struct ZoneMonitor *zm;
2063
2064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n");
2065 zm = GNUNET_new (struct ZoneMonitor);
2066 zm->nc = nc;
2067 zm->zone = zis_msg->zone;
2068 zm->limit = 1;
2069 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2070 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2071 GNUNET_SERVICE_client_mark_monitor (nc->client);
2072 GNUNET_SERVICE_client_continue (nc->client);
2073 GNUNET_notification_context_add (monitor_nc, nc->mq);
2074 if (zm->in_first_iteration)
2075 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2076 else
2077 monitor_sync (zm);
2078}
2079
2080
2081/**
2082 * Obtain the next datum during the zone monitor's zone initial iteration.
2083 *
2084 * @param cls zone monitor that does its initial iteration
2085 */
2086static void
2087monitor_iteration_next (void *cls)
2088{
2089 struct ZoneMonitor *zm = cls;
2090 int ret;
2091
2092 zm->task = NULL;
2093 GNUNET_assert (0 == zm->iteration_cnt);
2094 if (zm->limit > 16)
2095 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2096 else
2097 zm->iteration_cnt = zm->limit; /* use it all */
2098 ret = GSN_database->iterate_records (GSN_database->cls,
2099 (GNUNET_YES == GNUNET_is_zero (
2100 &zm->zone))
2101 ? NULL
2102 : &zm->zone,
2103 zm->seq,
2104 zm->iteration_cnt,
2105 &monitor_iterate_cb,
2106 zm);
2107 if (GNUNET_SYSERR == ret)
2108 {
2109 GNUNET_SERVICE_client_drop (zm->nc->client);
2110 return;
2111 }
2112 if (GNUNET_NO == ret)
2113 {
2114 /* empty zone */
2115 monitor_sync (zm);
2116 return;
2117 }
2118}
2119
2120
2121/**
2122 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2123 *
2124 * @param cls the client sending the message
2125 * @param nm message from the client
2126 */
2127static void
2128handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2129{
2130 struct NamestoreClient *nc = cls;
2131 struct ZoneMonitor *zm;
2132 uint64_t inc;
2133
2134 inc = GNUNET_ntohll (nm->limit);
2135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2136 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2137 (unsigned long long) inc);
2138 for (zm = monitor_head; NULL != zm; zm = zm->next)
2139 if (zm->nc == nc)
2140 break;
2141 if (NULL == zm)
2142 {
2143 GNUNET_break (0);
2144 GNUNET_SERVICE_client_drop (nc->client);
2145 return;
2146 }
2147 GNUNET_SERVICE_client_continue (nc->client);
2148 if (zm->limit + inc < zm->limit)
2149 {
2150 GNUNET_break (0);
2151 GNUNET_SERVICE_client_drop (nc->client);
2152 return;
2153 }
2154 zm->limit += inc;
2155 if ((zm->in_first_iteration) && (zm->limit == inc))
2156 {
2157 /* We are still iterating, and the previous iteration must
2158 have stopped due to the client's limit, so continue it! */
2159 GNUNET_assert (NULL == zm->task);
2160 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2161 }
2162 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2163 if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2164 {
2165 monitor_unblock (zm);
2166 }
2167 else if (GNUNET_YES == zm->sa_waiting)
2168 {
2169 if (NULL != zm->sa_wait_warning)
2170 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2171 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2172 zm->sa_wait_warning =
2173 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2174 &warn_monitor_slow,
2175 zm);
2176 }
2177}
2178
2179
2180/**
2181 * Process namestore requests.
2182 *
2183 * @param cls closure
2184 * @param cfg configuration to use
2185 * @param service the initialized service
2186 */
2187static void
2188run (void *cls,
2189 const struct GNUNET_CONFIGURATION_Handle *cfg,
2190 struct GNUNET_SERVICE_Handle *service)
2191{
2192 char *database;
2193
2194 (void) cls;
2195 (void) service;
2196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2197 cache_keys =
2198 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS");
2199 disable_namecache =
2200 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namecache", "DISABLE");
2201 GSN_cfg = cfg;
2202 monitor_nc = GNUNET_notification_context_create (1);
2203 if (GNUNET_YES != disable_namecache)
2204 {
2205 namecache = GNUNET_NAMECACHE_connect (cfg);
2206 GNUNET_assert (NULL != namecache);
2207 }
2208 /* Loading database plugin */
2209 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2210 "namestore",
2211 "database",
2212 &database))
2213 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2214
2215 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2216 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2217 GNUNET_free (database);
2218 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2219 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2220 if (NULL == GSN_database)
2221 {
2222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2223 "Could not load database backend `%s'\n",
2224 db_lib_name);
2225 GNUNET_SCHEDULER_shutdown ();
2226 return;
2227 }
2228}
2229
2230
2231/**
2232 * Define "main" method using service macro.
2233 */
2234GNUNET_SERVICE_MAIN (
2235 "namestore",
2236 GNUNET_SERVICE_OPTION_NONE,
2237 &run,
2238 &client_connect_cb,
2239 &client_disconnect_cb,
2240 NULL,
2241 GNUNET_MQ_hd_var_size (record_store,
2242 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2243 struct RecordStoreMessage,
2244 NULL),
2245 GNUNET_MQ_hd_var_size (record_lookup,
2246 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2247 struct LabelLookupMessage,
2248 NULL),
2249 GNUNET_MQ_hd_fixed_size (zone_to_name,
2250 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2251 struct ZoneToNameMessage,
2252 NULL),
2253 GNUNET_MQ_hd_fixed_size (iteration_start,
2254 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2255 struct ZoneIterationStartMessage,
2256 NULL),
2257 GNUNET_MQ_hd_fixed_size (iteration_next,
2258 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2259 struct ZoneIterationNextMessage,
2260 NULL),
2261 GNUNET_MQ_hd_fixed_size (iteration_stop,
2262 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2263 struct ZoneIterationStopMessage,
2264 NULL),
2265 GNUNET_MQ_hd_fixed_size (monitor_start,
2266 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2267 struct ZoneMonitorStartMessage,
2268 NULL),
2269 GNUNET_MQ_hd_fixed_size (monitor_next,
2270 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2271 struct ZoneMonitorNextMessage,
2272 NULL),
2273 GNUNET_MQ_handler_end ());
2274
2275
2276/* end of gnunet-service-namestore.c */