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