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.c2401
1 files changed, 0 insertions, 2401 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
deleted file mode 100644
index 6d3cc45ec..000000000
--- a/src/namestore/gnunet-service-namestore.c
+++ /dev/null
@@ -1,2401 +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 * A namestore client
126 */
127struct NamestoreClient
128{
129 /**
130 * The client
131 */
132 struct GNUNET_SERVICE_Client *client;
133
134 /**
135 * Message queue for transmission to @e client
136 */
137 struct GNUNET_MQ_Handle *mq;
138
139 /**
140 * Head of the DLL of
141 * Zone iteration operations in progress initiated by this client
142 */
143 struct ZoneIteration *op_head;
144
145 /**
146 * Tail of the DLL of
147 * Zone iteration operations in progress initiated by this client
148 */
149 struct ZoneIteration *op_tail;
150};
151
152
153/**
154 * A namestore monitor.
155 */
156struct ZoneMonitor
157{
158 /**
159 * Next element in the DLL
160 */
161 struct ZoneMonitor *next;
162
163 /**
164 * Previous element in the DLL
165 */
166 struct ZoneMonitor *prev;
167
168 /**
169 * Namestore client which intiated this zone monitor
170 */
171 struct NamestoreClient *nc;
172
173 /**
174 * Private key of the zone.
175 */
176 struct GNUNET_IDENTITY_PrivateKey zone;
177
178 /**
179 * Task active during initial iteration.
180 */
181 struct GNUNET_SCHEDULER_Task *task;
182
183 /**
184 * Task to warn about slow monitors.
185 */
186 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
187
188 /**
189 * Since when are we blocked on this monitor?
190 */
191 struct GNUNET_TIME_Absolute sa_waiting_start;
192
193 /**
194 * Last sequence number in the zone iteration used to address next
195 * result of the zone iteration in the store
196 *
197 * Initially set to 0.
198 * Updated in #monitor_iterate_cb()
199 */
200 uint64_t seq;
201
202 /**
203 * Current limit of how many more messages we are allowed
204 * to queue to this monitor.
205 */
206 uint64_t limit;
207
208 /**
209 * How many more requests may we receive from the iterator
210 * before it is at the limit we gave it? Will be below or
211 * equal to @e limit. The effective limit for monitor
212 * events is thus @e iteration_cnt - @e limit!
213 */
214 uint64_t iteration_cnt;
215
216 /**
217 * Are we (still) in the initial iteration pass?
218 */
219 int in_first_iteration;
220
221 /**
222 * Is there a store activity waiting for this monitor? We only raise the
223 * flag when it happens and search the DLL for the store activity when we
224 * had a limit increase. If we cannot find any waiting store activity at
225 * that time, we clear the flag again.
226 */
227 int sa_waiting;
228};
229
230
231/**
232 * Pending operation on the namecache.
233 */
234struct CacheOperation
235{
236 /**
237 * Kept in a DLL.
238 */
239 struct CacheOperation *prev;
240
241 /**
242 * Kept in a DLL.
243 */
244 struct CacheOperation *next;
245
246 /**
247 * Handle to namecache queue.
248 */
249 struct GNUNET_NAMECACHE_QueueEntry *qe;
250
251 /**
252 * Client to notify about the result, can be NULL.
253 */
254 struct NamestoreClient *nc;
255
256 /**
257 * Zone iteration to call #zone_iteration_done_client_continue()
258 * for if applicable, can be NULL.
259 */
260 struct ZoneIteration *zi;
261
262 /**
263 * Client's request ID.
264 */
265 uint32_t rid;
266};
267
268
269/**
270 * Information for an ongoing #handle_record_store() operation.
271 * Needed as we may wait for monitors to be ready for the notification.
272 */
273struct StoreActivity
274{
275 /**
276 * Kept in a DLL.
277 */
278 struct StoreActivity *next;
279
280 /**
281 * Kept in a DLL.
282 */
283 struct StoreActivity *prev;
284
285 /**
286 * Which client triggered the store activity?
287 */
288 struct NamestoreClient *nc;
289
290 /**
291 * Copy of the original store message (as data fields in @e rd will
292 * point into it!).
293 */
294 const struct RecordStoreMessage *rsm;
295
296 /**
297 * Next zone monitor that still needs to be notified about this PUT.
298 */
299 struct ZoneMonitor *zm_pos;
300
301 /**
302 * Label nicely canonicalized (lower case).
303 */
304 char *conv_name;
305};
306
307
308/**
309 * Entry in list of cached nick resolutions.
310 */
311struct NickCache
312{
313 /**
314 * Zone the cache entry is for.
315 */
316 struct GNUNET_IDENTITY_PrivateKey zone;
317
318 /**
319 * Cached record data.
320 */
321 struct GNUNET_GNSRECORD_Data *rd;
322
323 /**
324 * Timestamp when this cache entry was used last.
325 */
326 struct GNUNET_TIME_Absolute last_used;
327};
328
329
330/**
331 * We cache nick records to reduce DB load.
332 */
333static struct NickCache nick_cache[NC_SIZE];
334
335/**
336 * Public key of all zeros.
337 */
338static const struct GNUNET_IDENTITY_PrivateKey zero;
339
340/**
341 * Configuration handle.
342 */
343static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
344
345/**
346 * Handle to the statistics service
347 */
348static struct GNUNET_STATISTICS_Handle *statistics;
349
350/**
351 * Namecache handle.
352 */
353static struct GNUNET_NAMECACHE_Handle *namecache;
354
355/**
356 * Database handle
357 */
358static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
359
360/**
361 * Name of the database plugin
362 */
363static char *db_lib_name;
364
365/**
366 * Head of cop DLL.
367 */
368static struct CacheOperation *cop_head;
369
370/**
371 * Tail of cop DLL.
372 */
373static struct CacheOperation *cop_tail;
374
375/**
376 * First active zone monitor.
377 */
378static struct ZoneMonitor *monitor_head;
379
380/**
381 * Last active zone monitor.
382 */
383static struct ZoneMonitor *monitor_tail;
384
385/**
386 * Head of DLL of monitor-blocked store activities.
387 */
388static struct StoreActivity *sa_head;
389
390/**
391 * Tail of DLL of monitor-blocked store activities.
392 */
393static struct StoreActivity *sa_tail;
394
395/**
396 * Notification context shared by all monitors.
397 */
398static struct GNUNET_NotificationContext *monitor_nc;
399
400/**
401 * Optimize block insertion by caching map of private keys to
402 * public keys in memory?
403 */
404static int cache_keys;
405
406/**
407 * Use the namecache? Doing so creates additional cryptographic
408 * operations whenever we touch a record.
409 */
410static int disable_namecache;
411
412
413/**
414 * Task run during shutdown.
415 *
416 * @param cls unused
417 */
418static void
419cleanup_task (void *cls)
420{
421 struct CacheOperation *cop;
422
423 (void) cls;
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
425 while (NULL != (cop = cop_head))
426 {
427 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
428 "Aborting incomplete namecache operation\n");
429 GNUNET_NAMECACHE_cancel (cop->qe);
430 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
431 GNUNET_free (cop);
432 }
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, const char*emsg,
812 uint32_t rid)
813{
814 struct GNUNET_MQ_Envelope *env;
815 struct RecordStoreResponseMessage *rcr_msg;
816
817 GNUNET_assert (NULL != nc);
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
819 "Sending RECORD_STORE_RESPONSE message\n");
820 GNUNET_STATISTICS_update (statistics,
821 "Store requests completed",
822 1,
823 GNUNET_NO);
824 env = GNUNET_MQ_msg_extra (rcr_msg,
825 (NULL != emsg) ? strlen (emsg) + 1 : 0,
826 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
827 rcr_msg->gns_header.r_id = htonl (rid);
828 rcr_msg->op_result = htonl (res);
829 rcr_msg->reserved = htons (0);
830 if (NULL != emsg)
831 {
832 rcr_msg->emsg_len = htons (strlen (emsg) + 1);
833 memcpy (&rcr_msg[1], emsg, strlen (emsg) + 1);
834 }
835 GNUNET_MQ_send (nc->mq, env);
836}
837
838
839/**
840 * Function called once we are done with the zone iteration and
841 * allow the zone iteration client to send us more messages.
842 *
843 * @param zi zone iteration we are processing
844 */
845static void
846zone_iteration_done_client_continue (struct ZoneIteration *zi)
847{
848 struct GNUNET_MQ_Envelope *env;
849 struct GNUNET_NAMESTORE_Header *em;
850
851 GNUNET_SERVICE_client_continue (zi->nc->client);
852 if (! zi->send_end)
853 return;
854 /* send empty response to indicate end of list */
855 env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
856 em->r_id = htonl (zi->request_id);
857 GNUNET_MQ_send (zi->nc->mq, env);
858
859 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi);
860 GNUNET_free (zi);
861}
862
863
864/**
865 * Cache operation complete, clean up.
866 *
867 * @param cls the `struct CacheOperation`
868 * @param success success
869 * @param emsg error messages
870 */
871static void
872finish_cache_operation (void *cls, int32_t success, const char *emsg)
873{
874 struct CacheOperation *cop = cls;
875 struct ZoneIteration *zi;
876
877 if (NULL != emsg)
878 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
879 _ ("Failed to replicate block in namecache: %s\n"),
880 emsg);
881 else
882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
883 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
884 if (NULL != cop->nc)
885 send_store_response (cop->nc, success, emsg, cop->rid);
886 if (NULL != (zi = cop->zi))
887 {
888 zi->cache_ops--;
889 if (0 == zi->cache_ops)
890 {
891 /* unchoke zone iteration, cache has caught up */
892 zone_iteration_done_client_continue (zi);
893 }
894 }
895 GNUNET_free (cop);
896}
897
898
899/**
900 * We just touched the plaintext information about a name in our zone;
901 * refresh the corresponding (encrypted) block in the namecache.
902 *
903 * @param nc client responsible for the request, can be NULL
904 * @param zi zone iteration response for the request, can be NULL
905 * @param rid request ID of the client
906 * @param zone_key private key of the zone
907 * @param name label for the records
908 * @param rd_count number of records
909 * @param rd records stored under the given @a name
910 */
911static void
912refresh_block (struct NamestoreClient *nc,
913 struct ZoneIteration *zi,
914 uint32_t rid,
915 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
916 const char *name,
917 unsigned int rd_count,
918 const struct GNUNET_GNSRECORD_Data *rd)
919{
920 struct GNUNET_GNSRECORD_Block *block;
921 struct GNUNET_GNSRECORD_Data rd_clean[rd_count];
922 struct CacheOperation *cop;
923 struct GNUNET_IDENTITY_PublicKey pkey;
924 struct GNUNET_GNSRECORD_Data *nick;
925 struct GNUNET_GNSRECORD_Data *res;
926 unsigned int res_count;
927 unsigned int rd_count_clean;
928 struct GNUNET_TIME_Absolute exp_time;
929
930 /** Do not block-cache tombstones */
931 rd_count_clean = 0;
932 for (int i = 0; i < rd_count; i++)
933 {
934 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
935 continue;
936 rd_clean[rd_count_clean++] = rd[i];
937 }
938
939 nick = get_nick_record (zone_key);
940 res_count = rd_count_clean;
941 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */
942 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
943 {
944 nick->flags =
945 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
946 merge_with_nick_records (nick, rd_count_clean, rd_clean, &res_count, &res);
947 }
948 if (NULL != nick)
949 GNUNET_free (nick);
950 if (0 == res_count)
951 {
952 if (NULL != nc)
953 send_store_response (nc, GNUNET_OK, NULL, rid);
954 if (rd_clean != res)
955 GNUNET_free (res);
956 return; /* no data, no need to update cache */
957 }
958 if (GNUNET_YES == disable_namecache)
959 {
960 GNUNET_STATISTICS_update (statistics,
961 "Namecache updates skipped (NC disabled)",
962 1,
963 GNUNET_NO);
964 if (NULL != nc)
965 send_store_response (nc, GNUNET_OK, NULL, rid);
966 if (rd_clean != res)
967 GNUNET_free (res);
968 return;
969 }
970 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res,
971 GNUNET_TIME_UNIT_ZERO_ABS);
972 if (cache_keys)
973 GNUNET_assert (GNUNET_OK ==
974 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name,
975 res, res_count, &block));
976 else
977 GNUNET_assert (GNUNET_OK ==
978 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name,
979 res, res_count, &block));
980 GNUNET_assert (NULL != block);
981 GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
982 GNUNET_log (
983 GNUNET_ERROR_TYPE_DEBUG,
984 "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
985 name,
986 res_count,
987 GNUNET_STRINGS_absolute_time_to_string (exp_time),
988 GNUNET_GNSRECORD_z2s (&pkey));
989 GNUNET_STATISTICS_update (statistics,
990 "Namecache updates pushed",
991 1,
992 GNUNET_NO);
993 cop = GNUNET_new (struct CacheOperation);
994 cop->nc = nc;
995 cop->zi = zi;
996 if (NULL != zi)
997 zi->cache_ops ++;
998 cop->rid = rid;
999 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
1000 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
1001 block,
1002 &finish_cache_operation,
1003 cop);
1004 GNUNET_free (block);
1005 if (rd_clean != res)
1006 GNUNET_free (res);
1007}
1008
1009
1010/**
1011 * Print a warning that one of our monitors is no longer reacting.
1012 *
1013 * @param cls a `struct ZoneMonitor` to warn about
1014 */
1015static void
1016warn_monitor_slow (void *cls)
1017{
1018 struct ZoneMonitor *zm = cls;
1019
1020 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1021 "No response from monitor since %s\n",
1022 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
1023 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1024 &warn_monitor_slow,
1025 zm);
1026}
1027
1028
1029/**
1030 * Continue processing the @a sa.
1031 *
1032 * @param sa store activity to process
1033 */
1034static void
1035continue_store_activity (struct StoreActivity *sa)
1036{
1037 const struct RecordStoreMessage *rp_msg = sa->rsm;
1038 unsigned int rd_count;
1039 size_t name_len;
1040 size_t rd_ser_len;
1041 uint32_t rid;
1042 const char *name_tmp;
1043 const char *rd_ser;
1044
1045 rid = ntohl (rp_msg->gns_header.r_id);
1046 name_len = ntohs (rp_msg->name_len);
1047 rd_count = ntohs (rp_msg->rd_count);
1048 rd_ser_len = ntohs (rp_msg->rd_len);
1049 name_tmp = (const char *) &rp_msg[1];
1050 rd_ser = &name_tmp[name_len];
1051 {
1052 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1053
1054 /* We did this before, must succeed again */
1055 GNUNET_assert (
1056 GNUNET_OK ==
1057 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd));
1058
1059 for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos)
1060 {
1061 if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) &&
1062 (0 != GNUNET_memcmp (&zm->zone, &zero)))
1063 {
1064 sa->zm_pos = zm->next; /* not interesting to this monitor */
1065 continue;
1066 }
1067 if (zm->limit == zm->iteration_cnt)
1068 {
1069 zm->sa_waiting = GNUNET_YES;
1070 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1071 if (NULL != zm->sa_wait_warning)
1072 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1073 zm->sa_wait_warning =
1074 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1075 &warn_monitor_slow,
1076 zm);
1077 return; /* blocked on zone monitor */
1078 }
1079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080 "Notifying monitor about changes under label `%s'\n",
1081 sa->conv_name);
1082 zm->limit--;
1083 send_lookup_response (zm->nc,
1084 0,
1085 &rp_msg->private_key,
1086 sa->conv_name,
1087 rd_count,
1088 rd);
1089 sa->zm_pos = zm->next;
1090 }
1091 /* great, done with the monitors, unpack (again) for refresh_block operation */
1092 refresh_block (sa->nc,
1093 NULL,
1094 rid,
1095 &rp_msg->private_key,
1096 sa->conv_name,
1097 rd_count,
1098 rd);
1099 }
1100 GNUNET_SERVICE_client_continue (sa->nc->client);
1101 free_store_activity (sa);
1102}
1103
1104
1105/**
1106 * Called whenever a client is disconnected.
1107 * Frees our resources associated with that client.
1108 *
1109 * @param cls closure
1110 * @param client identification of the client
1111 * @param app_ctx the `struct NamestoreClient` of @a client
1112 */
1113static void
1114client_disconnect_cb (void *cls,
1115 struct GNUNET_SERVICE_Client *client,
1116 void *app_ctx)
1117{
1118 struct NamestoreClient *nc = app_ctx;
1119 struct ZoneIteration *no;
1120 struct CacheOperation *cop;
1121
1122 (void) cls;
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1124 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1125 {
1126 struct StoreActivity *san;
1127
1128 if (nc != zm->nc)
1129 continue;
1130 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm);
1131 if (NULL != zm->task)
1132 {
1133 GNUNET_SCHEDULER_cancel (zm->task);
1134 zm->task = NULL;
1135 }
1136 if (NULL != zm->sa_wait_warning)
1137 {
1138 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1139 zm->sa_wait_warning = NULL;
1140 }
1141 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1142 {
1143 san = sa->next;
1144 if (zm == sa->zm_pos)
1145 {
1146 sa->zm_pos = zm->next;
1147 /* this may free sa */
1148 continue_store_activity (sa);
1149 }
1150 }
1151 GNUNET_free (zm);
1152 break;
1153 }
1154 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1155 {
1156 if (sa->nc == nc)
1157 {
1158 /* this may free sa */
1159 free_store_activity (sa);
1160 break; /* there can only be one per nc */
1161 }
1162 }
1163 while (NULL != (no = nc->op_head))
1164 {
1165 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
1166 GNUNET_free (no);
1167 }
1168 for (cop = cop_head; NULL != cop; cop = cop->next)
1169 if (nc == cop->nc)
1170 cop->nc = NULL;
1171 GNUNET_free (nc);
1172}
1173
1174
1175/**
1176 * Add a client to our list of active clients.
1177 *
1178 * @param cls NULL
1179 * @param client client to add
1180 * @param mq message queue for @a client
1181 * @return internal namestore client structure for this client
1182 */
1183static void *
1184client_connect_cb (void *cls,
1185 struct GNUNET_SERVICE_Client *client,
1186 struct GNUNET_MQ_Handle *mq)
1187{
1188 struct NamestoreClient *nc;
1189
1190 (void) cls;
1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1192 nc = GNUNET_new (struct NamestoreClient);
1193 nc->client = client;
1194 nc->mq = mq;
1195 return nc;
1196}
1197
1198
1199/**
1200 * Closure for #lookup_it().
1201 */
1202struct RecordLookupContext
1203{
1204 /**
1205 * FIXME.
1206 */
1207 const char *label;
1208
1209 /**
1210 * FIXME.
1211 */
1212 char *res_rd;
1213
1214 /**
1215 * FIXME.
1216 */
1217 struct GNUNET_GNSRECORD_Data *nick;
1218
1219 /**
1220 * FIXME.
1221 */
1222 int found;
1223
1224 /**
1225 * FIXME.
1226 */
1227 unsigned int res_rd_count;
1228
1229 /**
1230 * FIXME.
1231 */
1232 ssize_t rd_ser_len;
1233};
1234
1235
1236/**
1237 * Function called by the namestore plugin when we are trying to lookup
1238 * a record as part of #handle_record_lookup(). Merges all results into
1239 * the context.
1240 *
1241 * @param cls closure with a `struct RecordLookupContext`
1242 * @param seq unique serial number of the record, MUST NOT BE ZERO
1243 * @param zone_key private key of the zone
1244 * @param label name that is being mapped (at most 255 characters long)
1245 * @param rd_count number of entries in @a rd array
1246 * @param rd array of records with data to store
1247 */
1248static void
1249lookup_it (void *cls,
1250 uint64_t seq,
1251 const struct GNUNET_IDENTITY_PrivateKey *private_key,
1252 const char *label,
1253 unsigned int rd_count,
1254 const struct GNUNET_GNSRECORD_Data *rd)
1255{
1256 struct RecordLookupContext *rlc = cls;
1257
1258 (void) private_key;
1259 GNUNET_assert (0 != seq);
1260 if (0 != strcmp (label, rlc->label))
1261 return;
1262 rlc->found = GNUNET_YES;
1263 if (0 == rd_count)
1264 {
1265 rlc->rd_ser_len = 0;
1266 rlc->res_rd_count = 0;
1267 rlc->res_rd = NULL;
1268 return;
1269 }
1270 if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)))
1271 {
1272 /* Merge */
1273 struct GNUNET_GNSRECORD_Data *rd_res;
1274 unsigned int rdc_res;
1275
1276 rd_res = NULL;
1277 rdc_res = 0;
1278 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE)
1279 ^ GNUNET_GNSRECORD_RF_PRIVATE;
1280 merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res);
1281 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res);
1282 if (rlc->rd_ser_len < 0)
1283 {
1284 GNUNET_break (0);
1285 GNUNET_free (rd_res);
1286 rlc->found = GNUNET_NO;
1287 rlc->rd_ser_len = 0;
1288 return;
1289 }
1290 rlc->res_rd_count = rdc_res;
1291 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1292 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res,
1293 rd_res,
1294 rlc->rd_ser_len,
1295 rlc->res_rd))
1296 {
1297 GNUNET_break (0);
1298 GNUNET_free (rlc->res_rd);
1299 rlc->res_rd = NULL;
1300 rlc->res_rd_count = 0;
1301 rlc->rd_ser_len = 0;
1302 GNUNET_free (rd_res);
1303 rlc->found = GNUNET_NO;
1304 return;
1305 }
1306 GNUNET_free (rd_res);
1307 GNUNET_free (rlc->nick);
1308 rlc->nick = NULL;
1309 }
1310 else
1311 {
1312 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1313 if (rlc->rd_ser_len < 0)
1314 {
1315 GNUNET_break (0);
1316 rlc->found = GNUNET_NO;
1317 rlc->rd_ser_len = 0;
1318 return;
1319 }
1320 rlc->res_rd_count = rd_count;
1321 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1322 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count,
1323 rd,
1324 rlc->rd_ser_len,
1325 rlc->res_rd))
1326 {
1327 GNUNET_break (0);
1328 GNUNET_free (rlc->res_rd);
1329 rlc->res_rd = NULL;
1330 rlc->res_rd_count = 0;
1331 rlc->rd_ser_len = 0;
1332 rlc->found = GNUNET_NO;
1333 return;
1334 }
1335 }
1336}
1337
1338
1339/**
1340 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1341 *
1342 * @param cls client sending the message
1343 * @param ll_msg message of type `struct LabelLookupMessage`
1344 * @return #GNUNET_OK if @a ll_msg is well-formed
1345 */
1346static int
1347check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1348{
1349 uint32_t name_len;
1350 size_t src_size;
1351
1352 (void) cls;
1353 name_len = ntohl (ll_msg->label_len);
1354 src_size = ntohs (ll_msg->gns_header.header.size);
1355 if (name_len != src_size - sizeof(struct LabelLookupMessage))
1356 {
1357 GNUNET_break (0);
1358 return GNUNET_SYSERR;
1359 }
1360 GNUNET_MQ_check_zero_termination (ll_msg);
1361 return GNUNET_OK;
1362}
1363
1364
1365/**
1366 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1367 *
1368 * @param cls client sending the message
1369 * @param ll_msg message of type `struct LabelLookupMessage`
1370 */
1371static void
1372handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1373{
1374 struct NamestoreClient *nc = cls;
1375 struct GNUNET_MQ_Envelope *env;
1376 struct LabelLookupResponseMessage *llr_msg;
1377 struct RecordLookupContext rlc;
1378 const char *name_tmp;
1379 char *res_name;
1380 char *conv_name;
1381 uint32_t name_len;
1382 int res;
1383
1384 name_tmp = (const char *) &ll_msg[1];
1385 GNUNET_SERVICE_client_continue (nc->client);
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1387 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1388 name_tmp);
1389
1390 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1391 if (NULL == conv_name)
1392 {
1393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1394 "Error converting name `%s'\n",
1395 name_tmp);
1396 GNUNET_SERVICE_client_drop (nc->client);
1397 return;
1398 }
1399 name_len = strlen (conv_name) + 1;
1400 rlc.label = conv_name;
1401 rlc.found = GNUNET_NO;
1402 rlc.res_rd_count = 0;
1403 rlc.res_rd = NULL;
1404 rlc.rd_ser_len = 0;
1405 rlc.nick = get_nick_record (&ll_msg->zone);
1406 res = GSN_database->lookup_records (GSN_database->cls,
1407 &ll_msg->zone,
1408 conv_name,
1409 &lookup_it,
1410 &rlc);
1411 env =
1412 GNUNET_MQ_msg_extra (llr_msg,
1413 name_len + rlc.rd_ser_len,
1414 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1415 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1416 llr_msg->private_key = ll_msg->zone;
1417 llr_msg->name_len = htons (name_len);
1418 llr_msg->rd_count = htons (rlc.res_rd_count);
1419 llr_msg->rd_len = htons (rlc.rd_ser_len);
1420 res_name = (char *) &llr_msg[1];
1421 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1422 llr_msg->found = htons (GNUNET_YES);
1423 else
1424 llr_msg->found = htons (GNUNET_NO);
1425 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1426 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1427 GNUNET_MQ_send (nc->mq, env);
1428 GNUNET_free (rlc.res_rd);
1429 GNUNET_free (conv_name);
1430}
1431
1432
1433
1434/**
1435 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1436 *
1437 * @param cls client sending the message
1438 * @param rp_msg message of type `struct RecordStoreMessage`
1439 * @return #GNUNET_OK if @a rp_msg is well-formed
1440 */
1441static int
1442check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1443{
1444 size_t name_len;
1445 size_t msg_size;
1446 size_t msg_size_exp;
1447 size_t rd_ser_len;
1448 const char *name_tmp;
1449
1450 (void) cls;
1451 name_len = ntohs (rp_msg->name_len);
1452 msg_size = ntohs (rp_msg->gns_header.header.size);
1453 rd_ser_len = ntohs (rp_msg->rd_len);
1454 msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len;
1455 if (msg_size != msg_size_exp)
1456 {
1457 GNUNET_break (0);
1458 return GNUNET_SYSERR;
1459 }
1460 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1461 {
1462 GNUNET_break (0);
1463 return GNUNET_SYSERR;
1464 }
1465 name_tmp = (const char *) &rp_msg[1];
1466 if ('\0' != name_tmp[name_len - 1])
1467 {
1468 GNUNET_break (0);
1469 return GNUNET_SYSERR;
1470 }
1471 return GNUNET_OK;
1472}
1473
1474
1475/**
1476 * Check if set contains a tombstone, store if necessary
1477 *
1478 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
1479 * @param seq sequence number of the record, MUST NOT BE ZERO
1480 * @param private_key the private key of the zone (unused)
1481 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
1482 * @param rd_count number of records in @a rd
1483 * @param rd records stored under @a label in the zone
1484 */
1485static void
1486get_block_exp_existing (void *cls,
1487 uint64_t seq,
1488 const struct
1489 GNUNET_IDENTITY_PrivateKey *private_key,
1490 const char *label,
1491 unsigned int rd_count,
1492 const struct GNUNET_GNSRECORD_Data *rd)
1493{
1494 struct GNUNET_TIME_Absolute *exp = cls;
1495 struct GNUNET_GNSRECORD_Data rd_pub[rd_count];
1496 unsigned int rd_pub_count;
1497 char *emsg;
1498
1499 if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label,
1500 rd,
1501 rd_count,
1502 rd_pub,
1503 &rd_pub_count,
1504 exp,
1505 &emsg))
1506 {
1507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1508 "%s\n", emsg);
1509 GNUNET_free (emsg);
1510 }
1511}
1512
1513
1514/**
1515 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1516 *
1517 * @param cls client sending the message
1518 * @param rp_msg message of type `struct RecordStoreMessage`
1519 */
1520static void
1521handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1522{
1523 struct NamestoreClient *nc = cls;
1524 size_t name_len;
1525 size_t rd_ser_len;
1526 uint32_t rid;
1527 const char *name_tmp;
1528 char *conv_name;
1529 const char *rd_ser;
1530 unsigned int rd_count;
1531 int res;
1532 struct StoreActivity *sa;
1533 struct GNUNET_TIME_Absolute existing_block_exp;
1534 struct GNUNET_TIME_Absolute new_block_exp;
1535
1536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1537 "Received NAMESTORE_RECORD_STORE message\n");
1538 existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1539 new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1540 rid = ntohl (rp_msg->gns_header.r_id);
1541 name_len = ntohs (rp_msg->name_len);
1542 rd_count = ntohs (rp_msg->rd_count);
1543 rd_ser_len = ntohs (rp_msg->rd_len);
1544 name_tmp = (const char *) &rp_msg[1];
1545 rd_ser = &name_tmp[name_len];
1546 {
1547 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1548 char *emsg;
1549
1550 /* Extracting and converting private key */
1551 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1552 if (NULL == conv_name)
1553 {
1554 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1555 "Error normalizing name `%s'\n",
1556 name_tmp);
1557 send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."),
1558 rid);
1559 GNUNET_SERVICE_client_continue (nc->client);
1560 return;
1561 }
1562
1563 /* Check name for validity */
1564 if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg))
1565 {
1566 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1567 "Label invalid: `%s'\n",
1568 emsg);
1569 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1570 GNUNET_free (emsg);
1571 GNUNET_free (conv_name);
1572 GNUNET_SERVICE_client_continue (nc->client);
1573 return;
1574 }
1575
1576 if (GNUNET_OK !=
1577 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1578 {
1579 send_store_response (nc, GNUNET_SYSERR,
1580 _ ("Error deserializing records."), rid);
1581 GNUNET_free (conv_name);
1582 GNUNET_SERVICE_client_continue (nc->client);
1583 return;
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 == GSN_database->lookup_records (GSN_database->cls,
1595 &rp_msg->private_key,
1596 conv_name,
1597 &get_block_exp_existing,
1598 &existing_block_exp)) &&
1599 (rd_count == 0))
1600 {
1601 /* This name does not exist, so cannot be removed */
1602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1603 "Name `%s' does not exist, no deletion required\n",
1604 conv_name);
1605 res = GNUNET_NO;
1606 }
1607 else
1608 {
1609 /* remove "NICK" records, unless this is for the
1610 #GNUNET_GNS_EMPTY_LABEL_AT label
1611 We may need one additional record later for tombstone.
1612 FIXME: Since we must normalize the record set (check for
1613 consistency etc) we have to iterate the set twice.
1614 May be inefficient.
1615 We cannot really move the nick caching into GNSRECORD.
1616 */
1617 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1618 struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1];
1619 unsigned int rd_clean_off;
1620 unsigned int rd_nf_count;
1621 char *emsg;
1622 int have_nick;
1623
1624 rd_clean_off = 0;
1625 have_nick = GNUNET_NO;
1626 for (unsigned int i = 0; i < rd_count; i++)
1627 {
1628 rd_clean[rd_clean_off] = rd[i];
1629
1630 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1631 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1632 rd_clean_off++;
1633
1634 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1635 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
1636 {
1637 cache_nick (&rp_msg->private_key, &rd[i]);
1638 have_nick = GNUNET_YES;
1639 }
1640 }
1641 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (conv_name,
1642 rd_clean,
1643 rd_clean_off,
1644 rd_nf,
1645 &rd_nf_count,
1646 &new_block_exp,
1647 GNUNET_YES,
1648 &emsg))
1649 {
1650 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1651 GNUNET_free (emsg);
1652 GNUNET_SERVICE_client_continue (nc->client);
1653 GNUNET_free (conv_name);
1654 return;
1655 }
1656 /*
1657 * If existing_block_exp is 0, then there was not record set
1658 * and no tombstone.
1659 * Otherwise, if the existing block expiration is after the
1660 * new block expiration would be, we need to add a tombstone
1661 * or update it.
1662 */
1663 if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, existing_block_exp))
1664 {
1665 rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
1666 rd_nf[rd_nf_count].expiration_time =
1667 existing_block_exp.abs_value_us;
1668 rd_nf[rd_nf_count].data = NULL;
1669 rd_nf[rd_nf_count].data_size = 0;
1670 rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1671 rd_nf_count++;
1672 }
1673 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1674 (GNUNET_NO == have_nick))
1675 {
1676 /* remove nick record from cache, in case we have one there */
1677 cache_nick (&rp_msg->private_key, NULL);
1678 }
1679 res = GSN_database->store_records (GSN_database->cls,
1680 &rp_msg->private_key,
1681 conv_name,
1682 rd_nf_count,
1683 rd_nf);
1684 }
1685
1686 if (GNUNET_OK != res)
1687 {
1688 /* store not successful, no need to tell monitors */
1689 send_store_response (nc, res, _ ("Store failed"), rid);
1690 GNUNET_SERVICE_client_continue (nc->client);
1691 GNUNET_free (conv_name);
1692 return;
1693 }
1694 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1695 + ntohs (rp_msg->gns_header.header.size));
1696 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1697 sa->nc = nc;
1698 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1699 GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size));
1700 sa->zm_pos = monitor_head;
1701 sa->conv_name = conv_name;
1702 continue_store_activity (sa);
1703 }
1704}
1705
1706
1707/**
1708 * Context for record remove operations passed from #handle_zone_to_name to
1709 * #handle_zone_to_name_it as closure
1710 */
1711struct ZoneToNameCtx
1712{
1713 /**
1714 * Namestore client
1715 */
1716 struct NamestoreClient *nc;
1717
1718 /**
1719 * Request id (to be used in the response to the client).
1720 */
1721 uint32_t rid;
1722
1723 /**
1724 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1725 * not finding a name for the zone still counts as a 'success' here,
1726 * as this field is about the success of executing the IPC protocol.
1727 */
1728 int success;
1729};
1730
1731
1732/**
1733 * Zone to name iterator
1734 *
1735 * @param cls struct ZoneToNameCtx *
1736 * @param seq sequence number of the record, MUST NOT BE ZERO
1737 * @param zone_key the zone key
1738 * @param name name
1739 * @param rd_count number of records in @a rd
1740 * @param rd record data
1741 */
1742static void
1743handle_zone_to_name_it (void *cls,
1744 uint64_t seq,
1745 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1746 const char *name,
1747 unsigned int rd_count,
1748 const struct GNUNET_GNSRECORD_Data *rd)
1749{
1750 struct ZoneToNameCtx *ztn_ctx = cls;
1751 struct GNUNET_MQ_Envelope *env;
1752 struct ZoneToNameResponseMessage *ztnr_msg;
1753 int16_t res;
1754 size_t name_len;
1755 ssize_t rd_ser_len;
1756 size_t msg_size;
1757 char *name_tmp;
1758 char *rd_tmp;
1759
1760 GNUNET_assert (0 != seq);
1761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1762 "Found result for zone-to-name lookup: `%s'\n",
1763 name);
1764 res = GNUNET_YES;
1765 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1766 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1767 if (rd_ser_len < 0)
1768 {
1769 GNUNET_break (0);
1770 ztn_ctx->success = GNUNET_SYSERR;
1771 return;
1772 }
1773 msg_size = sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1774 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1775 {
1776 GNUNET_break (0);
1777 ztn_ctx->success = GNUNET_SYSERR;
1778 return;
1779 }
1780 env =
1781 GNUNET_MQ_msg_extra (ztnr_msg,
1782 name_len + rd_ser_len,
1783 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1784 ztnr_msg->gns_header.header.size = htons (msg_size);
1785 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1786 ztnr_msg->res = htons (res);
1787 ztnr_msg->rd_len = htons (rd_ser_len);
1788 ztnr_msg->rd_count = htons (rd_count);
1789 ztnr_msg->name_len = htons (name_len);
1790 ztnr_msg->zone = *zone_key;
1791 name_tmp = (char *) &ztnr_msg[1];
1792 GNUNET_memcpy (name_tmp, name, name_len);
1793 rd_tmp = &name_tmp[name_len];
1794 GNUNET_assert (
1795 rd_ser_len ==
1796 GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
1797 ztn_ctx->success = GNUNET_OK;
1798 GNUNET_MQ_send (ztn_ctx->nc->mq, env);
1799}
1800
1801
1802/**
1803 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1804 *
1805 * @param cls client client sending the message
1806 * @param ztn_msg message of type 'struct ZoneToNameMessage'
1807 */
1808static void
1809handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
1810{
1811 struct NamestoreClient *nc = cls;
1812 struct ZoneToNameCtx ztn_ctx;
1813 struct GNUNET_MQ_Envelope *env;
1814 struct ZoneToNameResponseMessage *ztnr_msg;
1815
1816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
1817 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1818 ztn_ctx.nc = nc;
1819 ztn_ctx.success = GNUNET_NO;
1820 if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls,
1821 &ztn_msg->zone,
1822 &ztn_msg->value_zone,
1823 &handle_zone_to_name_it,
1824 &ztn_ctx))
1825 {
1826 /* internal error, hang up instead of signalling something
1827 that might be wrong */
1828 GNUNET_break (0);
1829 GNUNET_SERVICE_client_drop (nc->client);
1830 return;
1831 }
1832 if (GNUNET_NO == ztn_ctx.success)
1833 {
1834 /* no result found, send empty response */
1835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1836 "Found no result for zone-to-name lookup.\n");
1837 env = GNUNET_MQ_msg (ztnr_msg,
1838 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1839 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1840 ztnr_msg->res = htons (GNUNET_NO);
1841 GNUNET_MQ_send (nc->mq, env);
1842 }
1843 GNUNET_SERVICE_client_continue (nc->client);
1844}
1845
1846
1847/**
1848 * Context for record remove operations passed from
1849 * #run_zone_iteration_round to #zone_iterate_proc as closure
1850 */
1851struct ZoneIterationProcResult
1852{
1853 /**
1854 * The zone iteration handle
1855 */
1856 struct ZoneIteration *zi;
1857
1858 /**
1859 * Number of results left to be returned in this iteration.
1860 */
1861 uint64_t limit;
1862};
1863
1864
1865/**
1866 * Process results for zone iteration from database
1867 *
1868 * @param cls struct ZoneIterationProcResult
1869 * @param seq sequence number of the record, MUST NOT BE ZERO
1870 * @param zone_key the zone key
1871 * @param name name
1872 * @param rd_count number of records for this name
1873 * @param rd record data
1874 */
1875static void
1876zone_iterate_proc (void *cls,
1877 uint64_t seq,
1878 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1879 const char *name,
1880 unsigned int rd_count,
1881 const struct GNUNET_GNSRECORD_Data *rd)
1882{
1883 struct ZoneIterationProcResult *proc = cls;
1884 int do_refresh_block;
1885
1886 GNUNET_assert (0 != seq);
1887 if ((NULL == zone_key) && (NULL == name))
1888 {
1889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1890 return;
1891 }
1892 if ((NULL == zone_key) || (NULL == name))
1893 {
1894 /* what is this!? should never happen */
1895 GNUNET_break (0);
1896 return;
1897 }
1898 if (0 == proc->limit)
1899 {
1900 /* what is this!? should never happen */
1901 GNUNET_break (0);
1902 return;
1903 }
1904 proc->limit--;
1905 proc->zi->seq = seq;
1906 send_lookup_response (proc->zi->nc,
1907 proc->zi->request_id,
1908 zone_key,
1909 name,
1910 rd_count,
1911 rd);
1912
1913
1914 do_refresh_block = GNUNET_NO;
1915 for (unsigned int i = 0; i < rd_count; i++)
1916 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1917 {
1918 do_refresh_block = GNUNET_YES;
1919 break;
1920 }
1921 if (GNUNET_YES == do_refresh_block)
1922 refresh_block (NULL, proc->zi, 0, zone_key, name, rd_count, rd);
1923}
1924
1925
1926/**
1927 * Perform the next round of the zone iteration.
1928 *
1929 * @param zi zone iterator to process
1930 * @param limit number of results to return in one pass
1931 */
1932static void
1933run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
1934{
1935 struct ZoneIterationProcResult proc;
1936 struct GNUNET_TIME_Absolute start;
1937 struct GNUNET_TIME_Relative duration;
1938
1939 memset (&proc, 0, sizeof(proc));
1940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1941 "Asked to return up to %llu records at position %llu\n",
1942 (unsigned long long) limit,
1943 (unsigned long long) zi->seq);
1944 proc.zi = zi;
1945 proc.limit = limit;
1946 start = GNUNET_TIME_absolute_get ();
1947 GNUNET_break (GNUNET_SYSERR !=
1948 GSN_database->iterate_records (GSN_database->cls,
1949 (GNUNET_YES == GNUNET_is_zero (
1950 &zi->zone))
1951 ? NULL
1952 : &zi->zone,
1953 zi->seq,
1954 limit,
1955 &zone_iterate_proc,
1956 &proc));
1957 duration = GNUNET_TIME_absolute_get_duration (start);
1958 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
1959 GNUNET_STATISTICS_set (statistics,
1960 "NAMESTORE iteration delay (μs/record)",
1961 duration.rel_value_us,
1962 GNUNET_NO);
1963 if (0 == proc.limit)
1964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1965 "Returned %llu results, more results available\n",
1966 (unsigned long long) limit);
1967 zi->send_end = (0 != proc.limit);
1968 if (0 == zi->cache_ops)
1969 zone_iteration_done_client_continue (zi);
1970}
1971
1972
1973/**
1974 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1975 *
1976 * @param cls the client sending the message
1977 * @param zis_msg message from the client
1978 */
1979static void
1980handle_iteration_start (void *cls,
1981 const struct ZoneIterationStartMessage *zis_msg)
1982{
1983 struct NamestoreClient *nc = cls;
1984 struct ZoneIteration *zi;
1985
1986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1987 "Received ZONE_ITERATION_START message\n");
1988 zi = GNUNET_new (struct ZoneIteration);
1989 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1990 zi->offset = 0;
1991 zi->nc = nc;
1992 zi->zone = zis_msg->zone;
1993
1994 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1995 run_zone_iteration_round (zi, 1);
1996}
1997
1998
1999/**
2000 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
2001 *
2002 * @param cls the client sending the message
2003 * @param zis_msg message from the client
2004 */
2005static void
2006handle_iteration_stop (void *cls,
2007 const struct ZoneIterationStopMessage *zis_msg)
2008{
2009 struct NamestoreClient *nc = cls;
2010 struct ZoneIteration *zi;
2011 uint32_t rid;
2012
2013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2014 "Received ZONE_ITERATION_STOP message\n");
2015 rid = ntohl (zis_msg->gns_header.r_id);
2016 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2017 if (zi->request_id == rid)
2018 break;
2019 if (NULL == zi)
2020 {
2021 GNUNET_break (0);
2022 GNUNET_SERVICE_client_drop (nc->client);
2023 return;
2024 }
2025 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2026 GNUNET_free (zi);
2027 GNUNET_SERVICE_client_continue (nc->client);
2028}
2029
2030
2031/**
2032 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
2033 *
2034 * @param cls the client sending the message
2035 * @param message message from the client
2036 */
2037static void
2038handle_iteration_next (void *cls,
2039 const struct ZoneIterationNextMessage *zis_msg)
2040{
2041 struct NamestoreClient *nc = cls;
2042 struct ZoneIteration *zi;
2043 uint32_t rid;
2044 uint64_t limit;
2045
2046 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2047 "Received ZONE_ITERATION_NEXT message\n");
2048 GNUNET_STATISTICS_update (statistics,
2049 "Iteration NEXT messages received",
2050 1,
2051 GNUNET_NO);
2052 rid = ntohl (zis_msg->gns_header.r_id);
2053 limit = GNUNET_ntohll (zis_msg->limit);
2054 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2055 if (zi->request_id == rid)
2056 break;
2057 if (NULL == zi)
2058 {
2059 GNUNET_break (0);
2060 GNUNET_SERVICE_client_drop (nc->client);
2061 return;
2062 }
2063 run_zone_iteration_round (zi, limit);
2064}
2065
2066
2067/**
2068 * Function called when the monitor is ready for more data, and we
2069 * should thus unblock PUT operations that were blocked on the
2070 * monitor not being ready.
2071 */
2072static void
2073monitor_unblock (struct ZoneMonitor *zm)
2074{
2075 struct StoreActivity *sa = sa_head;
2076
2077 while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
2078 {
2079 struct StoreActivity *sn = sa->next;
2080
2081 if (sa->zm_pos == zm)
2082 continue_store_activity (sa);
2083 sa = sn;
2084 }
2085 if (zm->limit > zm->iteration_cnt)
2086 {
2087 zm->sa_waiting = GNUNET_NO;
2088 if (NULL != zm->sa_wait_warning)
2089 {
2090 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2091 zm->sa_wait_warning = NULL;
2092 }
2093 }
2094 else if (GNUNET_YES == zm->sa_waiting)
2095 {
2096 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2097 if (NULL != zm->sa_wait_warning)
2098 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2099 zm->sa_wait_warning =
2100 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2101 &warn_monitor_slow,
2102 zm);
2103 }
2104}
2105
2106
2107/**
2108 * Send 'sync' message to zone monitor, we're now in sync.
2109 *
2110 * @param zm monitor that is now in sync
2111 */
2112static void
2113monitor_sync (struct ZoneMonitor *zm)
2114{
2115 struct GNUNET_MQ_Envelope *env;
2116 struct GNUNET_MessageHeader *sync;
2117
2118 env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
2119 GNUNET_MQ_send (zm->nc->mq, env);
2120 /* mark iteration done */
2121 zm->in_first_iteration = GNUNET_NO;
2122 zm->iteration_cnt = 0;
2123 if ((zm->limit > 0) && (zm->sa_waiting))
2124 monitor_unblock (zm);
2125}
2126
2127
2128/**
2129 * Obtain the next datum during the zone monitor's zone initial iteration.
2130 *
2131 * @param cls zone monitor that does its initial iteration
2132 */
2133static void
2134monitor_iteration_next (void *cls);
2135
2136
2137/**
2138 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2139 *
2140 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2141 * @param seq sequence number of the record, MUST NOT BE ZERO
2142 * @param zone_key zone key of the zone
2143 * @param name name
2144 * @param rd_count number of records in @a rd
2145 * @param rd array of records
2146 */
2147static void
2148monitor_iterate_cb (void *cls,
2149 uint64_t seq,
2150 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2151 const char *name,
2152 unsigned int rd_count,
2153 const struct GNUNET_GNSRECORD_Data *rd)
2154{
2155 struct ZoneMonitor *zm = cls;
2156
2157 GNUNET_assert (0 != seq);
2158 zm->seq = seq;
2159 GNUNET_assert (NULL != name);
2160 GNUNET_STATISTICS_update (statistics,
2161 "Monitor notifications sent",
2162 1,
2163 GNUNET_NO);
2164 zm->limit--;
2165 zm->iteration_cnt--;
2166 send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd);
2167 if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2168 {
2169 /* We are done with the current iteration batch, AND the
2170 client would right now accept more, so go again! */
2171 GNUNET_assert (NULL == zm->task);
2172 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2173 }
2174}
2175
2176
2177/**
2178 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2179 *
2180 * @param cls the client sending the message
2181 * @param zis_msg message from the client
2182 */
2183static void
2184handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg)
2185{
2186 struct NamestoreClient *nc = cls;
2187 struct ZoneMonitor *zm;
2188
2189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n");
2190 zm = GNUNET_new (struct ZoneMonitor);
2191 zm->nc = nc;
2192 zm->zone = zis_msg->zone;
2193 zm->limit = 1;
2194 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2195 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2196 GNUNET_SERVICE_client_mark_monitor (nc->client);
2197 GNUNET_SERVICE_client_continue (nc->client);
2198 GNUNET_notification_context_add (monitor_nc, nc->mq);
2199 if (zm->in_first_iteration)
2200 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2201 else
2202 monitor_sync (zm);
2203}
2204
2205
2206/**
2207 * Obtain the next datum during the zone monitor's zone initial iteration.
2208 *
2209 * @param cls zone monitor that does its initial iteration
2210 */
2211static void
2212monitor_iteration_next (void *cls)
2213{
2214 struct ZoneMonitor *zm = cls;
2215 int ret;
2216
2217 zm->task = NULL;
2218 GNUNET_assert (0 == zm->iteration_cnt);
2219 if (zm->limit > 16)
2220 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2221 else
2222 zm->iteration_cnt = zm->limit; /* use it all */
2223 ret = GSN_database->iterate_records (GSN_database->cls,
2224 (GNUNET_YES == GNUNET_is_zero (
2225 &zm->zone))
2226 ? NULL
2227 : &zm->zone,
2228 zm->seq,
2229 zm->iteration_cnt,
2230 &monitor_iterate_cb,
2231 zm);
2232 if (GNUNET_SYSERR == ret)
2233 {
2234 GNUNET_SERVICE_client_drop (zm->nc->client);
2235 return;
2236 }
2237 if (GNUNET_NO == ret)
2238 {
2239 /* empty zone */
2240 monitor_sync (zm);
2241 return;
2242 }
2243}
2244
2245
2246/**
2247 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2248 *
2249 * @param cls the client sending the message
2250 * @param nm message from the client
2251 */
2252static void
2253handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2254{
2255 struct NamestoreClient *nc = cls;
2256 struct ZoneMonitor *zm;
2257 uint64_t inc;
2258
2259 inc = GNUNET_ntohll (nm->limit);
2260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2261 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2262 (unsigned long long) inc);
2263 for (zm = monitor_head; NULL != zm; zm = zm->next)
2264 if (zm->nc == nc)
2265 break;
2266 if (NULL == zm)
2267 {
2268 GNUNET_break (0);
2269 GNUNET_SERVICE_client_drop (nc->client);
2270 return;
2271 }
2272 GNUNET_SERVICE_client_continue (nc->client);
2273 if (zm->limit + inc < zm->limit)
2274 {
2275 GNUNET_break (0);
2276 GNUNET_SERVICE_client_drop (nc->client);
2277 return;
2278 }
2279 zm->limit += inc;
2280 if ((zm->in_first_iteration) && (zm->limit == inc))
2281 {
2282 /* We are still iterating, and the previous iteration must
2283 have stopped due to the client's limit, so continue it! */
2284 GNUNET_assert (NULL == zm->task);
2285 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2286 }
2287 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2288 if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2289 {
2290 monitor_unblock (zm);
2291 }
2292 else if (GNUNET_YES == zm->sa_waiting)
2293 {
2294 if (NULL != zm->sa_wait_warning)
2295 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2296 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2297 zm->sa_wait_warning =
2298 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2299 &warn_monitor_slow,
2300 zm);
2301 }
2302}
2303
2304
2305/**
2306 * Process namestore requests.
2307 *
2308 * @param cls closure
2309 * @param cfg configuration to use
2310 * @param service the initialized service
2311 */
2312static void
2313run (void *cls,
2314 const struct GNUNET_CONFIGURATION_Handle *cfg,
2315 struct GNUNET_SERVICE_Handle *service)
2316{
2317 char *database;
2318
2319 (void) cls;
2320 (void) service;
2321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2322 cache_keys =
2323 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS");
2324 disable_namecache =
2325 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namecache", "DISABLE");
2326 GSN_cfg = cfg;
2327 monitor_nc = GNUNET_notification_context_create (1);
2328 if (GNUNET_YES != disable_namecache)
2329 {
2330 namecache = GNUNET_NAMECACHE_connect (cfg);
2331 GNUNET_assert (NULL != namecache);
2332 }
2333 /* Loading database plugin */
2334 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2335 "namestore",
2336 "database",
2337 &database))
2338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2339
2340 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2341 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2342 GNUNET_free (database);
2343 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2344 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2345 if (NULL == GSN_database)
2346 {
2347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2348 "Could not load database backend `%s'\n",
2349 db_lib_name);
2350 GNUNET_SCHEDULER_shutdown ();
2351 return;
2352 }
2353}
2354
2355
2356/**
2357 * Define "main" method using service macro.
2358 */
2359GNUNET_SERVICE_MAIN (
2360 "namestore",
2361 GNUNET_SERVICE_OPTION_NONE,
2362 &run,
2363 &client_connect_cb,
2364 &client_disconnect_cb,
2365 NULL,
2366 GNUNET_MQ_hd_var_size (record_store,
2367 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2368 struct RecordStoreMessage,
2369 NULL),
2370 GNUNET_MQ_hd_var_size (record_lookup,
2371 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2372 struct LabelLookupMessage,
2373 NULL),
2374 GNUNET_MQ_hd_fixed_size (zone_to_name,
2375 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2376 struct ZoneToNameMessage,
2377 NULL),
2378 GNUNET_MQ_hd_fixed_size (iteration_start,
2379 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2380 struct ZoneIterationStartMessage,
2381 NULL),
2382 GNUNET_MQ_hd_fixed_size (iteration_next,
2383 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2384 struct ZoneIterationNextMessage,
2385 NULL),
2386 GNUNET_MQ_hd_fixed_size (iteration_stop,
2387 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2388 struct ZoneIterationStopMessage,
2389 NULL),
2390 GNUNET_MQ_hd_fixed_size (monitor_start,
2391 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2392 struct ZoneMonitorStartMessage,
2393 NULL),
2394 GNUNET_MQ_hd_fixed_size (monitor_next,
2395 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2396 struct ZoneMonitorNextMessage,
2397 NULL),
2398 GNUNET_MQ_handler_end ());
2399
2400
2401/* end of gnunet-service-namestore.c */