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