GNUnet  0.11.x
gnunet-service-namestore.c
Go to the documentation of this file.
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 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dnsparser_lib.h"
30 #include "gnunet_gns_service.h"
35 #include "gnunet_signatures.h"
36 #include "namestore.h"
37 
38 #define LOG_STRERROR_FILE(kind, syscall, filename) \
39  GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
40 
44 #define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
45 
49 #define NC_SIZE 16
50 
54 struct NamestoreClient;
55 
56 
61 {
66 
71 
76 
81 
86 
94  uint64_t seq;
95 
99  uint32_t request_id;
100 
108  uint32_t offset;
109 
114  unsigned int cache_ops;
115 
121  int send_end;
122 };
123 
124 
129 {
134 
139 
145 
151 };
152 
153 
158 {
162  struct ZoneMonitor *next;
163 
167  struct ZoneMonitor *prev;
168 
173 
178 
183 
188 
192  struct GNUNET_TIME_Absolute sa_waiting_start;
193 
201  uint64_t seq;
202 
207  uint64_t limit;
208 
215  uint64_t iteration_cnt;
216 
221 
229 };
230 
231 
236 {
241 
246 
251 
256 
261  struct ZoneIteration *zi;
262 
266  uint32_t rid;
267 };
268 
269 
275 {
280 
285 
290 
295  const struct RecordStoreMessage *rsm;
296 
301 
305  char *conv_name;
306 };
307 
308 
312 struct NickCache
313 {
318 
323 
327  struct GNUNET_TIME_Absolute last_used;
328 };
329 
330 
334 static struct NickCache nick_cache[NC_SIZE];
335 
339 static const struct GNUNET_IDENTITY_PrivateKey zero;
340 
345 
350 
355 
360 
364 static char *db_lib_name;
365 
369 static struct CacheOperation *cop_head;
370 
374 static struct CacheOperation *cop_tail;
375 
379 static struct ZoneMonitor *monitor_head;
380 
384 static struct ZoneMonitor *monitor_tail;
385 
389 static struct StoreActivity *sa_head;
390 
394 static struct StoreActivity *sa_tail;
395 
400 
405 static int cache_keys;
406 
411 static int disable_namecache;
412 
413 
419 static void
420 cleanup_task (void *cls)
421 {
422  struct CacheOperation *cop;
423 
424  (void) cls;
425  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
426  while (NULL != (cop = cop_head))
427  {
429  "Aborting incomplete namecache operation\n");
431  GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
432  GNUNET_free (cop);
433  }
434  if (NULL != namecache)
435  {
436  GNUNET_NAMECACHE_disconnect (namecache);
437  namecache = NULL;
438  }
439  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
441  db_lib_name = NULL;
442  if (NULL != monitor_nc)
443  {
445  monitor_nc = NULL;
446  }
447  if (NULL != statistics)
448  {
449  GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
450  statistics = NULL;
451  }
452 }
453 
454 
460 static void
462 {
463  GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa);
464  GNUNET_free (sa->conv_name);
465  GNUNET_free (sa);
466 }
467 
468 
481 static void
482 lookup_nick_it (void *cls,
483  uint64_t seq,
484  const struct GNUNET_IDENTITY_PrivateKey *private_key,
485  const char *label,
486  unsigned int rd_count,
487  const struct GNUNET_GNSRECORD_Data *rd)
488 {
489  struct GNUNET_GNSRECORD_Data **res = cls;
490 
491  (void) private_key;
492  GNUNET_assert (0 != seq);
493  if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
494  {
495  GNUNET_break (0);
496  return;
497  }
498  for (unsigned int c = 0; c < rd_count; c++)
499  {
501  {
502  (*res) =
503  GNUNET_malloc (rd[c].data_size + sizeof(struct GNUNET_GNSRECORD_Data));
504  (*res)->data = &(*res)[1];
505  GNUNET_memcpy ((void *) (*res)->data, rd[c].data, rd[c].data_size);
506  (*res)->data_size = rd[c].data_size;
507  (*res)->expiration_time = rd[c].expiration_time;
508  (*res)->flags = rd[c].flags;
509  (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
510  return;
511  }
512  }
513  (*res) = NULL;
514 }
515 
516 
523 static void
525  const struct GNUNET_GNSRECORD_Data *nick)
526 {
527  struct NickCache *oldest;
528 
529  oldest = NULL;
530  for (unsigned int i = 0; i < NC_SIZE; i++)
531  {
532  struct NickCache *pos = &nick_cache[i];
533 
534  if ((NULL == oldest) ||
535  (oldest->last_used.abs_value_us > pos->last_used.abs_value_us))
536  oldest = pos;
537  if (0 == GNUNET_memcmp (zone, &pos->zone))
538  {
539  oldest = pos;
540  break;
541  }
542  }
543  GNUNET_free (oldest->rd);
544  oldest->zone = *zone;
545  if (NULL != nick)
546  {
547  oldest->rd = GNUNET_malloc (sizeof(*nick) + nick->data_size);
548  *oldest->rd = *nick;
549  oldest->rd->data = &oldest->rd[1];
550  memcpy (&oldest->rd[1], nick->data, nick->data_size);
551  }
552  else
553  {
554  oldest->rd = NULL;
555  }
556  oldest->last_used = GNUNET_TIME_absolute_get ();
557 }
558 
559 
566 static struct GNUNET_GNSRECORD_Data *
568 {
569  struct GNUNET_IDENTITY_PublicKey pub;
570  struct GNUNET_GNSRECORD_Data *nick;
571  int res;
572 
573  /* check cache first */
574  for (unsigned int i = 0; i < NC_SIZE; i++)
575  {
576  struct NickCache *pos = &nick_cache[i];
577  if ((NULL != pos->rd) && (0 == GNUNET_memcmp (zone, &pos->zone)))
578  {
579  if (NULL == pos->rd)
580  return NULL;
581  nick = GNUNET_malloc (sizeof(*nick) + pos->rd->data_size);
582  *nick = *pos->rd;
583  nick->data = &nick[1];
584  memcpy (&nick[1], pos->rd->data, pos->rd->data_size);
586  return nick;
587  }
588  }
589 
590  nick = NULL;
591  res = GSN_database->lookup_records (GSN_database->cls,
592  zone,
595  &nick);
596  if ((GNUNET_OK != res) || (NULL == nick))
597  {
598 #if ! defined(GNUNET_CULL_LOGGING)
599  static int do_log = GNUNET_LOG_CALL_STATUS;
600 
601  if (0 == do_log)
603  "namestore",
604  __FILE__,
605  __FUNCTION__,
606  __LINE__);
607  if (1 == do_log)
608  {
609  GNUNET_IDENTITY_key_get_public (zone, &pub);
611  "No nick name set for zone `%s'\n",
612  GNUNET_GNSRECORD_z2s (&pub));
613  }
614 #endif
615  /* update cache */
616  cache_nick (zone, NULL);
617  return NULL;
618  }
619 
620  /* update cache */
621  cache_nick (zone, nick);
622  return nick;
623 }
624 
625 
641 static void
643  unsigned int rd2_length,
644  const struct GNUNET_GNSRECORD_Data *rd2,
645  unsigned int *rdc_res,
646  struct GNUNET_GNSRECORD_Data **rd_res)
647 {
648  uint64_t latest_expiration;
649  size_t req;
650  char *data;
651  size_t data_offset;
652  struct GNUNET_GNSRECORD_Data *target;
653 
654  (*rdc_res) = 1 + rd2_length;
655  if (0 == 1 + rd2_length)
656  {
657  GNUNET_break (0);
658  (*rd_res) = NULL;
659  return;
660  }
661  req = sizeof(struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
662  for (unsigned int i = 0; i < rd2_length; i++)
663  {
664  const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
665 
666  if (req + sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
667  {
668  GNUNET_break (0);
669  (*rd_res) = NULL;
670  return;
671  }
672  req += sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size;
673  }
674  target = GNUNET_malloc (req);
675  (*rd_res) = target;
676  data = (char *) &target[1 + rd2_length];
677  data_offset = 0;
678  latest_expiration = 0;
679  for (unsigned int i = 0; i < rd2_length; i++)
680  {
681  const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
682 
684  {
685  if ((GNUNET_TIME_absolute_get ().abs_value_us + orig->expiration_time) >
686  latest_expiration)
687  latest_expiration = orig->expiration_time;
688  }
689  else if (orig->expiration_time > latest_expiration)
690  latest_expiration = orig->expiration_time;
691  target[i] = *orig;
692  target[i].data = (void *) &data[data_offset];
693  GNUNET_memcpy (&data[data_offset], orig->data, orig->data_size);
694  data_offset += orig->data_size;
695  }
696  /* append nick */
697  target[rd2_length] = *nick_rd;
698  /* Mark as supplemental */
699  target[rd2_length].flags = nick_rd->flags | GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
700  target[rd2_length].expiration_time = latest_expiration;
701  target[rd2_length].data = (void *) &data[data_offset];
702  GNUNET_memcpy (&data[data_offset], nick_rd->data, nick_rd->data_size);
703  data_offset += nick_rd->data_size;
704  GNUNET_assert (req == (sizeof(struct GNUNET_GNSRECORD_Data)) * (*rdc_res)
705  + data_offset);
706 }
707 
708 
720 static void
722  uint32_t request_id,
723  const struct GNUNET_IDENTITY_PrivateKey *zone_key,
724  const char *name,
725  unsigned int rd_count,
726  const struct GNUNET_GNSRECORD_Data *rd)
727 {
728  struct GNUNET_MQ_Envelope *env;
729  struct RecordResultMessage *zir_msg;
730  struct GNUNET_GNSRECORD_Data *nick;
731  struct GNUNET_GNSRECORD_Data *res;
732  unsigned int res_count;
733  size_t name_len;
734  ssize_t rd_ser_len;
735  char *name_tmp;
736  char *rd_ser;
737 
738  nick = get_nick_record (zone_key);
739  GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
740 
741  if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
742  {
743  nick->flags =
745  merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
746  }
747  else
748  {
749  res_count = rd_count;
750  res = (struct GNUNET_GNSRECORD_Data *) rd;
751  }
752  if (NULL != nick)
753  GNUNET_free (nick);
754 
755  GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res));
756 
757 
758  name_len = strlen (name) + 1;
759  rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
760  if (rd_ser_len < 0)
761  {
762  if (rd != res)
763  GNUNET_free (res);
764  GNUNET_break (0);
766  return;
767  }
768  if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg))
769  {
770  if (rd != res)
771  GNUNET_free (res);
772  GNUNET_break (0);
774  return;
775  }
776  env = GNUNET_MQ_msg_extra (zir_msg,
777  name_len + rd_ser_len,
779  zir_msg->gns_header.r_id = htonl (request_id);
780  zir_msg->name_len = htons (name_len);
781  zir_msg->rd_count = htons (res_count);
782  zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
783  zir_msg->private_key = *zone_key;
784  name_tmp = (char *) &zir_msg[1];
785  GNUNET_memcpy (name_tmp, name, name_len);
786  rd_ser = &name_tmp[name_len];
787  GNUNET_assert (
788  rd_ser_len ==
789  GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser));
791  "Sending RECORD_RESULT message with %u records\n",
792  res_count);
793  GNUNET_STATISTICS_update (statistics,
794  "Record sets sent to clients",
795  1,
796  GNUNET_NO);
797  GNUNET_MQ_send (nc->mq, env);
798  if (rd != res)
799  GNUNET_free (res);
800 }
801 
802 
810 static void
811 send_store_response (struct NamestoreClient *nc, int res, uint32_t rid)
812 {
813  struct GNUNET_MQ_Envelope *env;
814  struct RecordStoreResponseMessage *rcr_msg;
815 
816  GNUNET_assert (NULL != nc);
818  "Sending RECORD_STORE_RESPONSE message\n");
819  GNUNET_STATISTICS_update (statistics,
820  "Store requests completed",
821  1,
822  GNUNET_NO);
823  env = GNUNET_MQ_msg (rcr_msg,
825  rcr_msg->gns_header.r_id = htonl (rid);
826  rcr_msg->op_result = htonl (res);
827  GNUNET_MQ_send (nc->mq, env);
828 }
829 
830 
837 static void
839 {
840  struct GNUNET_MQ_Envelope *env;
841  struct GNUNET_NAMESTORE_Header *em;
842 
844  if (! zi->send_end)
845  return;
846  /* send empty response to indicate end of list */
848  em->r_id = htonl (zi->request_id);
849  GNUNET_MQ_send (zi->nc->mq, env);
850 
852  GNUNET_free (zi);
853 }
854 
855 
863 static void
864 finish_cache_operation (void *cls, int32_t success, const char *emsg)
865 {
866  struct CacheOperation *cop = cls;
867  struct ZoneIteration *zi;
868 
869  if (NULL != emsg)
871  _ ("Failed to replicate block in namecache: %s\n"),
872  emsg);
873  else
874  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
875  GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
876  if (NULL != cop->nc)
877  send_store_response (cop->nc, success, cop->rid);
878  if (NULL != (zi = cop->zi))
879  {
880  zi->cache_ops--;
881  if (0 == zi->cache_ops)
882  {
883  /* unchoke zone iteration, cache has caught up */
885  }
886  }
887  GNUNET_free (cop);
888 }
889 
890 
903 static void
905  struct ZoneIteration *zi,
906  uint32_t rid,
907  const struct GNUNET_IDENTITY_PrivateKey *zone_key,
908  const char *name,
909  unsigned int rd_count,
910  const struct GNUNET_GNSRECORD_Data *rd)
911 {
912  struct GNUNET_GNSRECORD_Block *block;
913  struct CacheOperation *cop;
914  struct GNUNET_IDENTITY_PublicKey pkey;
915  struct GNUNET_GNSRECORD_Data *nick;
916  struct GNUNET_GNSRECORD_Data *res;
917  unsigned int res_count;
918  struct GNUNET_TIME_Absolute exp_time;
919 
920  nick = get_nick_record (zone_key);
921  res_count = rd_count;
922  res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
923  if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
924  {
925  nick->flags =
927  merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
928  }
929  if (NULL != nick)
930  GNUNET_free (nick);
931  if (0 == res_count)
932  {
933  if (NULL != nc)
934  send_store_response (nc, GNUNET_OK, rid);
935  if (rd != res)
936  GNUNET_free (res);
937  return; /* no data, no need to update cache */
938  }
940  {
941  GNUNET_STATISTICS_update (statistics,
942  "Namecache updates skipped (NC disabled)",
943  1,
944  GNUNET_NO);
945  if (NULL != nc)
946  send_store_response (nc, GNUNET_OK, rid);
947  if (rd != res)
948  GNUNET_free (res);
949  return;
950  }
951  exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res);
952  if (cache_keys)
953  block =
954  GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, res, res_count);
955  else
956  block =
957  GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, res, res_count);
958  GNUNET_assert (NULL != block);
959  GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
960  GNUNET_log (
962  "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
963  name,
964  res_count,
966  GNUNET_GNSRECORD_z2s (&pkey));
967  GNUNET_STATISTICS_update (statistics,
968  "Namecache updates pushed",
969  1,
970  GNUNET_NO);
971  cop = GNUNET_new (struct CacheOperation);
972  cop->nc = nc;
973  cop->zi = zi;
974  if (NULL != zi)
975  zi->cache_ops++;
976  cop->rid = rid;
977  GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
978  cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
979  block,
981  cop);
982  GNUNET_free (block);
983  if (rd != res)
984  GNUNET_free (res);
985 }
986 
987 
993 static void
994 warn_monitor_slow (void *cls)
995 {
996  struct ZoneMonitor *zm = cls;
997 
999  "No response from monitor since %s\n",
1003  zm);
1004 }
1005 
1006 
1012 static void
1014 {
1015  const struct RecordStoreMessage *rp_msg = sa->rsm;
1016  unsigned int rd_count;
1017  size_t name_len;
1018  size_t rd_ser_len;
1019  uint32_t rid;
1020  const char *name_tmp;
1021  const char *rd_ser;
1022 
1023  rid = ntohl (rp_msg->gns_header.r_id);
1024  name_len = ntohs (rp_msg->name_len);
1025  rd_count = ntohs (rp_msg->rd_count);
1026  rd_ser_len = ntohs (rp_msg->rd_len);
1027  name_tmp = (const char *) &rp_msg[1];
1028  rd_ser = &name_tmp[name_len];
1029  {
1030  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1031 
1032  /* We did this before, must succeed again */
1033  GNUNET_assert (
1034  GNUNET_OK ==
1035  GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd));
1036 
1037  for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos)
1038  {
1039  if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) &&
1040  (0 != GNUNET_memcmp (&zm->zone, &zero)))
1041  {
1042  sa->zm_pos = zm->next; /* not interesting to this monitor */
1043  continue;
1044  }
1045  if (zm->limit == zm->iteration_cnt)
1046  {
1047  zm->sa_waiting = GNUNET_YES;
1048  zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1049  if (NULL != zm->sa_wait_warning)
1050  GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1051  zm->sa_wait_warning =
1054  zm);
1055  return; /* blocked on zone monitor */
1056  }
1058  "Notifying monitor about changes under label `%s'\n",
1059  sa->conv_name);
1060  zm->limit--;
1061  send_lookup_response (zm->nc,
1062  0,
1063  &rp_msg->private_key,
1064  sa->conv_name,
1065  rd_count,
1066  rd);
1067  sa->zm_pos = zm->next;
1068  }
1069  /* great, done with the monitors, unpack (again) for refresh_block operation */
1070  refresh_block (sa->nc,
1071  NULL,
1072  rid,
1073  &rp_msg->private_key,
1074  sa->conv_name,
1075  rd_count,
1076  rd);
1077  }
1079  free_store_activity (sa);
1080 }
1081 
1082 
1091 static void
1093  struct GNUNET_SERVICE_Client *client,
1094  void *app_ctx)
1095 {
1096  struct NamestoreClient *nc = app_ctx;
1097  struct ZoneIteration *no;
1098  struct CacheOperation *cop;
1099 
1100  (void) cls;
1101  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1102  for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1103  {
1104  struct StoreActivity *san;
1105 
1106  if (nc != zm->nc)
1107  continue;
1108  GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm);
1109  if (NULL != zm->task)
1110  {
1111  GNUNET_SCHEDULER_cancel (zm->task);
1112  zm->task = NULL;
1113  }
1114  if (NULL != zm->sa_wait_warning)
1115  {
1116  GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1117  zm->sa_wait_warning = NULL;
1118  }
1119  for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1120  {
1121  san = sa->next;
1122  if (zm == sa->zm_pos)
1123  {
1124  sa->zm_pos = zm->next;
1125  /* this may free sa */
1127  }
1128  }
1129  GNUNET_free (zm);
1130  break;
1131  }
1132  for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1133  {
1134  if (sa->nc == nc)
1135  {
1136  /* this may free sa */
1137  free_store_activity (sa);
1138  break; /* there can only be one per nc */
1139  }
1140  }
1141  while (NULL != (no = nc->op_head))
1142  {
1144  GNUNET_free (no);
1145  }
1146  for (cop = cop_head; NULL != cop; cop = cop->next)
1147  if (nc == cop->nc)
1148  cop->nc = NULL;
1149  GNUNET_free (nc);
1150 }
1151 
1152 
1161 static void *
1163  struct GNUNET_SERVICE_Client *client,
1164  struct GNUNET_MQ_Handle *mq)
1165 {
1166  struct NamestoreClient *nc;
1167 
1168  (void) cls;
1169  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1170  nc = GNUNET_new (struct NamestoreClient);
1171  nc->client = client;
1172  nc->mq = mq;
1173  return nc;
1174 }
1175 
1176 
1181 {
1185  const char *label;
1186 
1190  char *res_rd;
1191 
1196 
1200  int found;
1201 
1205  unsigned int res_rd_count;
1206 
1210  ssize_t rd_ser_len;
1211 };
1212 
1213 
1226 static void
1227 lookup_it (void *cls,
1228  uint64_t seq,
1229  const struct GNUNET_IDENTITY_PrivateKey *private_key,
1230  const char *label,
1231  unsigned int rd_count,
1232  const struct GNUNET_GNSRECORD_Data *rd)
1233 {
1234  struct RecordLookupContext *rlc = cls;
1235 
1236  (void) private_key;
1237  GNUNET_assert (0 != seq);
1238  if (0 != strcmp (label, rlc->label))
1239  return;
1240  rlc->found = GNUNET_YES;
1241  if (0 == rd_count)
1242  {
1243  rlc->rd_ser_len = 0;
1244  rlc->res_rd_count = 0;
1245  rlc->res_rd = NULL;
1246  return;
1247  }
1248  if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)))
1249  {
1250  /* Merge */
1251  struct GNUNET_GNSRECORD_Data *rd_res;
1252  unsigned int rdc_res;
1253 
1254  rd_res = NULL;
1255  rdc_res = 0;
1256  rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE)
1258  merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res);
1259  rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res);
1260  if (rlc->rd_ser_len < 0)
1261  {
1262  GNUNET_break (0);
1263  GNUNET_free (rd_res);
1264  rlc->found = GNUNET_NO;
1265  rlc->rd_ser_len = 0;
1266  return;
1267  }
1268  rlc->res_rd_count = rdc_res;
1269  rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1270  if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res,
1271  rd_res,
1272  rlc->rd_ser_len,
1273  rlc->res_rd))
1274  {
1275  GNUNET_break (0);
1276  GNUNET_free (rlc->res_rd);
1277  rlc->res_rd = NULL;
1278  rlc->res_rd_count = 0;
1279  rlc->rd_ser_len = 0;
1280  GNUNET_free (rd_res);
1281  rlc->found = GNUNET_NO;
1282  return;
1283  }
1284  GNUNET_free (rd_res);
1285  GNUNET_free (rlc->nick);
1286  rlc->nick = NULL;
1287  }
1288  else
1289  {
1290  rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1291  if (rlc->rd_ser_len < 0)
1292  {
1293  GNUNET_break (0);
1294  rlc->found = GNUNET_NO;
1295  rlc->rd_ser_len = 0;
1296  return;
1297  }
1298  rlc->res_rd_count = rd_count;
1299  rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1300  if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count,
1301  rd,
1302  rlc->rd_ser_len,
1303  rlc->res_rd))
1304  {
1305  GNUNET_break (0);
1306  GNUNET_free (rlc->res_rd);
1307  rlc->res_rd = NULL;
1308  rlc->res_rd_count = 0;
1309  rlc->rd_ser_len = 0;
1310  rlc->found = GNUNET_NO;
1311  return;
1312  }
1313  }
1314 }
1315 
1316 
1324 static int
1325 check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1326 {
1327  uint32_t name_len;
1328  size_t src_size;
1329 
1330  (void) cls;
1331  name_len = ntohl (ll_msg->label_len);
1332  src_size = ntohs (ll_msg->gns_header.header.size);
1333  if (name_len != src_size - sizeof(struct LabelLookupMessage))
1334  {
1335  GNUNET_break (0);
1336  return GNUNET_SYSERR;
1337  }
1339  return GNUNET_OK;
1340 }
1341 
1342 
1349 static void
1350 handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1351 {
1352  struct NamestoreClient *nc = cls;
1353  struct GNUNET_MQ_Envelope *env;
1354  struct LabelLookupResponseMessage *llr_msg;
1355  struct RecordLookupContext rlc;
1356  const char *name_tmp;
1357  char *res_name;
1358  char *conv_name;
1359  uint32_t name_len;
1360  int res;
1361 
1362  name_len = ntohl (ll_msg->label_len);
1363  name_tmp = (const char *) &ll_msg[1];
1366  "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1367  name_tmp);
1368 
1369  conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1370  if (NULL == conv_name)
1371  {
1373  "Error converting name `%s'\n",
1374  name_tmp);
1376  return;
1377  }
1378  rlc.label = conv_name;
1379  rlc.found = GNUNET_NO;
1380  rlc.res_rd_count = 0;
1381  rlc.res_rd = NULL;
1382  rlc.rd_ser_len = 0;
1383  rlc.nick = get_nick_record (&ll_msg->zone);
1384  res = GSN_database->lookup_records (GSN_database->cls,
1385  &ll_msg->zone,
1386  conv_name,
1387  &lookup_it,
1388  &rlc);
1389  GNUNET_free (conv_name);
1390  env =
1391  GNUNET_MQ_msg_extra (llr_msg,
1392  name_len + rlc.rd_ser_len,
1394  llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1395  llr_msg->private_key = ll_msg->zone;
1396  llr_msg->name_len = htons (name_len);
1397  llr_msg->rd_count = htons (rlc.res_rd_count);
1398  llr_msg->rd_len = htons (rlc.rd_ser_len);
1399  res_name = (char *) &llr_msg[1];
1400  if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1401  llr_msg->found = ntohs (GNUNET_YES);
1402  else
1403  llr_msg->found = ntohs (GNUNET_NO);
1404  GNUNET_memcpy (&llr_msg[1], name_tmp, name_len);
1405  GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1406  GNUNET_MQ_send (nc->mq, env);
1407  GNUNET_free (rlc.res_rd);
1408 }
1409 
1410 
1418 static int
1419 check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1420 {
1421  size_t name_len;
1422  size_t msg_size;
1423  size_t msg_size_exp;
1424  size_t rd_ser_len;
1425  const char *name_tmp;
1426 
1427  (void) cls;
1428  name_len = ntohs (rp_msg->name_len);
1429  msg_size = ntohs (rp_msg->gns_header.header.size);
1430  rd_ser_len = ntohs (rp_msg->rd_len);
1431  msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len;
1432  if (msg_size != msg_size_exp)
1433  {
1434  GNUNET_break (0);
1435  return GNUNET_SYSERR;
1436  }
1437  if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1438  {
1439  GNUNET_break (0);
1440  return GNUNET_SYSERR;
1441  }
1442  name_tmp = (const char *) &rp_msg[1];
1443  if ('\0' != name_tmp[name_len - 1])
1444  {
1445  GNUNET_break (0);
1446  return GNUNET_SYSERR;
1447  }
1448  return GNUNET_OK;
1449 }
1450 
1451 
1458 static void
1459 handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1460 {
1461  struct NamestoreClient *nc = cls;
1462  size_t name_len;
1463  size_t rd_ser_len;
1464  uint32_t rid;
1465  const char *name_tmp;
1466  char *conv_name;
1467  const char *rd_ser;
1468  unsigned int rd_count;
1469  int res;
1470  struct StoreActivity *sa;
1471 
1473  "Received NAMESTORE_RECORD_STORE message\n");
1474  rid = ntohl (rp_msg->gns_header.r_id);
1475  name_len = ntohs (rp_msg->name_len);
1476  rd_count = ntohs (rp_msg->rd_count);
1477  rd_ser_len = ntohs (rp_msg->rd_len);
1478  GNUNET_break (0 == ntohs (rp_msg->reserved));
1479  name_tmp = (const char *) &rp_msg[1];
1480  rd_ser = &name_tmp[name_len];
1481  {
1482  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1483 
1484  if (GNUNET_OK !=
1485  GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1486  {
1487  GNUNET_break (0);
1489  return;
1490  }
1491 
1492  /* Extracting and converting private key */
1493  conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1494  if (NULL == conv_name)
1495  {
1497  "Error converting name `%s'\n",
1498  name_tmp);
1500  return;
1501  }
1502  GNUNET_STATISTICS_update (statistics,
1503  "Well-formed store requests received",
1504  1,
1505  GNUNET_NO);
1507  "Creating %u records for name `%s'\n",
1508  (unsigned int) rd_count,
1509  conv_name);
1510  if ((0 == rd_count) &&
1511  (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1512  &rp_msg->private_key,
1513  conv_name,
1514  NULL,
1515  0)))
1516  {
1517  /* This name does not exist, so cannot be removed */
1519  "Name `%s' does not exist, no deletion required\n",
1520  conv_name);
1521  res = GNUNET_NO;
1522  }
1523  else
1524  {
1525  /* remove "NICK" records, unless this is for the
1526  #GNUNET_GNS_EMPTY_LABEL_AT label */
1527  struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1528  unsigned int rd_clean_off;
1529  int have_nick;
1530 
1531  rd_clean_off = 0;
1532  have_nick = GNUNET_NO;
1533  for (unsigned int i = 0; i < rd_count; i++)
1534  {
1535  rd_clean[rd_clean_off] = rd[i];
1536  if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1538  rd_clean_off++;
1539 
1540  if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1541  (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
1542  {
1543  cache_nick (&rp_msg->private_key, &rd[i]);
1544  have_nick = GNUNET_YES;
1545  }
1546  }
1547  if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1548  (GNUNET_NO == have_nick))
1549  {
1550  /* remove nick record from cache, in case we have one there */
1551  cache_nick (&rp_msg->private_key, NULL);
1552  }
1553  res = GSN_database->store_records (GSN_database->cls,
1554  &rp_msg->private_key,
1555  conv_name,
1556  rd_clean_off,
1557  rd_clean);
1558  }
1559 
1560  if (GNUNET_OK != res)
1561  {
1562  /* store not successful, not need to tell monitors */
1563  send_store_response (nc, res, rid);
1565  GNUNET_free (conv_name);
1566  return;
1567  }
1568 
1569  sa = GNUNET_malloc (sizeof(struct StoreActivity)
1570  + ntohs (rp_msg->gns_header.header.size));
1571  GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1572  sa->nc = nc;
1573  sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1574  GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size));
1575  sa->zm_pos = monitor_head;
1576  sa->conv_name = conv_name;
1578  }
1579 }
1580 
1581 
1587 {
1592 
1596  uint32_t rid;
1597 
1603  int success;
1604 };
1605 
1606 
1617 static void
1619  uint64_t seq,
1620  const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1621  const char *name,
1622  unsigned int rd_count,
1623  const struct GNUNET_GNSRECORD_Data *rd)
1624 {
1625  struct ZoneToNameCtx *ztn_ctx = cls;
1626  struct GNUNET_MQ_Envelope *env;
1627  struct ZoneToNameResponseMessage *ztnr_msg;
1628  int16_t res;
1629  size_t name_len;
1630  ssize_t rd_ser_len;
1631  size_t msg_size;
1632  char *name_tmp;
1633  char *rd_tmp;
1634 
1635  GNUNET_assert (0 != seq);
1637  "Found result for zone-to-name lookup: `%s'\n",
1638  name);
1639  res = GNUNET_YES;
1640  name_len = (NULL == name) ? 0 : strlen (name) + 1;
1641  rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1642  if (rd_ser_len < 0)
1643  {
1644  GNUNET_break (0);
1645  ztn_ctx->success = GNUNET_SYSERR;
1646  return;
1647  }
1648  msg_size = sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1649  if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1650  {
1651  GNUNET_break (0);
1652  ztn_ctx->success = GNUNET_SYSERR;
1653  return;
1654  }
1655  env =
1656  GNUNET_MQ_msg_extra (ztnr_msg,
1657  name_len + rd_ser_len,
1659  ztnr_msg->gns_header.header.size = htons (msg_size);
1660  ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1661  ztnr_msg->res = htons (res);
1662  ztnr_msg->rd_len = htons (rd_ser_len);
1663  ztnr_msg->rd_count = htons (rd_count);
1664  ztnr_msg->name_len = htons (name_len);
1665  ztnr_msg->zone = *zone_key;
1666  name_tmp = (char *) &ztnr_msg[1];
1667  GNUNET_memcpy (name_tmp, name, name_len);
1668  rd_tmp = &name_tmp[name_len];
1669  GNUNET_assert (
1670  rd_ser_len ==
1671  GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
1672  ztn_ctx->success = GNUNET_OK;
1673  GNUNET_MQ_send (ztn_ctx->nc->mq, env);
1674 }
1675 
1676 
1683 static void
1684 handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
1685 {
1686  struct NamestoreClient *nc = cls;
1687  struct ZoneToNameCtx ztn_ctx;
1688  struct GNUNET_MQ_Envelope *env;
1689  struct ZoneToNameResponseMessage *ztnr_msg;
1690 
1691  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
1692  ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1693  ztn_ctx.nc = nc;
1694  ztn_ctx.success = GNUNET_NO;
1695  if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls,
1696  &ztn_msg->zone,
1697  &ztn_msg->value_zone,
1699  &ztn_ctx))
1700  {
1701  /* internal error, hang up instead of signalling something
1702  that might be wrong */
1703  GNUNET_break (0);
1705  return;
1706  }
1707  if (GNUNET_NO == ztn_ctx.success)
1708  {
1709  /* no result found, send empty response */
1711  "Found no result for zone-to-name lookup.\n");
1712  env = GNUNET_MQ_msg (ztnr_msg,
1714  ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1715  ztnr_msg->res = htons (GNUNET_NO);
1716  GNUNET_MQ_send (nc->mq, env);
1717  }
1719 }
1720 
1721 
1727 {
1732 
1736  uint64_t limit;
1737 };
1738 
1739 
1750 static void
1752  uint64_t seq,
1753  const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1754  const char *name,
1755  unsigned int rd_count,
1756  const struct GNUNET_GNSRECORD_Data *rd)
1757 {
1758  struct ZoneIterationProcResult *proc = cls;
1759  int do_refresh_block;
1760 
1761  GNUNET_assert (0 != seq);
1762  if ((NULL == zone_key) && (NULL == name))
1763  {
1764  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1765  return;
1766  }
1767  if ((NULL == zone_key) || (NULL == name))
1768  {
1769  /* what is this!? should never happen */
1770  GNUNET_break (0);
1771  return;
1772  }
1773  if (0 == proc->limit)
1774  {
1775  /* what is this!? should never happen */
1776  GNUNET_break (0);
1777  return;
1778  }
1779  proc->limit--;
1780  proc->zi->seq = seq;
1781  send_lookup_response (proc->zi->nc,
1782  proc->zi->request_id,
1783  zone_key,
1784  name,
1785  rd_count,
1786  rd);
1787 
1788 
1789  do_refresh_block = GNUNET_NO;
1790  for (unsigned int i = 0; i < rd_count; i++)
1791  if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1792  {
1793  do_refresh_block = GNUNET_YES;
1794  break;
1795  }
1796  if (GNUNET_YES == do_refresh_block)
1797  refresh_block (NULL, proc->zi, 0, zone_key, name, rd_count, rd);
1798 }
1799 
1800 
1807 static void
1809 {
1810  struct ZoneIterationProcResult proc;
1811  struct GNUNET_TIME_Absolute start;
1812  struct GNUNET_TIME_Relative duration;
1813 
1814  memset (&proc, 0, sizeof(proc));
1816  "Asked to return up to %llu records at position %llu\n",
1817  (unsigned long long) limit,
1818  (unsigned long long) zi->seq);
1819  proc.zi = zi;
1820  proc.limit = limit;
1821  start = GNUNET_TIME_absolute_get ();
1823  GSN_database->iterate_records (GSN_database->cls,
1825  &zi->zone))
1826  ? NULL
1827  : &zi->zone,
1828  zi->seq,
1829  limit,
1831  &proc));
1832  duration = GNUNET_TIME_absolute_get_duration (start);
1833  duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
1834  GNUNET_STATISTICS_set (statistics,
1835  "NAMESTORE iteration delay (μs/record)",
1836  duration.rel_value_us,
1837  GNUNET_NO);
1838  if (0 == proc.limit)
1840  "Returned %llu results, more results available\n",
1841  (unsigned long long) limit);
1842  zi->send_end = (0 != proc.limit);
1843  if (0 == zi->cache_ops)
1845 }
1846 
1847 
1854 static void
1856  const struct ZoneIterationStartMessage *zis_msg)
1857 {
1858  struct NamestoreClient *nc = cls;
1859  struct ZoneIteration *zi;
1860 
1862  "Received ZONE_ITERATION_START message\n");
1863  zi = GNUNET_new (struct ZoneIteration);
1864  zi->request_id = ntohl (zis_msg->gns_header.r_id);
1865  zi->offset = 0;
1866  zi->nc = nc;
1867  zi->zone = zis_msg->zone;
1868 
1870  run_zone_iteration_round (zi, 1);
1871 }
1872 
1873 
1880 static void
1882  const struct ZoneIterationStopMessage *zis_msg)
1883 {
1884  struct NamestoreClient *nc = cls;
1885  struct ZoneIteration *zi;
1886  uint32_t rid;
1887 
1889  "Received ZONE_ITERATION_STOP message\n");
1890  rid = ntohl (zis_msg->gns_header.r_id);
1891  for (zi = nc->op_head; NULL != zi; zi = zi->next)
1892  if (zi->request_id == rid)
1893  break;
1894  if (NULL == zi)
1895  {
1896  GNUNET_break (0);
1898  return;
1899  }
1901  GNUNET_free (zi);
1903 }
1904 
1905 
1912 static void
1914  const struct ZoneIterationNextMessage *zis_msg)
1915 {
1916  struct NamestoreClient *nc = cls;
1917  struct ZoneIteration *zi;
1918  uint32_t rid;
1919  uint64_t limit;
1920 
1922  "Received ZONE_ITERATION_NEXT message\n");
1923  GNUNET_STATISTICS_update (statistics,
1924  "Iteration NEXT messages received",
1925  1,
1926  GNUNET_NO);
1927  rid = ntohl (zis_msg->gns_header.r_id);
1928  limit = GNUNET_ntohll (zis_msg->limit);
1929  for (zi = nc->op_head; NULL != zi; zi = zi->next)
1930  if (zi->request_id == rid)
1931  break;
1932  if (NULL == zi)
1933  {
1934  GNUNET_break (0);
1936  return;
1937  }
1938  run_zone_iteration_round (zi, limit);
1939 }
1940 
1941 
1947 static void
1949 {
1950  struct StoreActivity *sa = sa_head;
1951 
1952  while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
1953  {
1954  struct StoreActivity *sn = sa->next;
1955 
1956  if (sa->zm_pos == zm)
1958  sa = sn;
1959  }
1960  if (zm->limit > zm->iteration_cnt)
1961  {
1962  zm->sa_waiting = GNUNET_NO;
1963  if (NULL != zm->sa_wait_warning)
1964  {
1966  zm->sa_wait_warning = NULL;
1967  }
1968  }
1969  else if (GNUNET_YES == zm->sa_waiting)
1970  {
1972  if (NULL != zm->sa_wait_warning)
1974  zm->sa_wait_warning =
1977  zm);
1978  }
1979 }
1980 
1981 
1987 static void
1989 {
1990  struct GNUNET_MQ_Envelope *env;
1991  struct GNUNET_MessageHeader *sync;
1992 
1994  GNUNET_MQ_send (zm->nc->mq, env);
1995  /* mark iteration done */
1997  zm->iteration_cnt = 0;
1998  if ((zm->limit > 0) && (zm->sa_waiting))
1999  monitor_unblock (zm);
2000 }
2001 
2002 
2008 static void
2009 monitor_iteration_next (void *cls);
2010 
2011 
2022 static void
2024  uint64_t seq,
2025  const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2026  const char *name,
2027  unsigned int rd_count,
2028  const struct GNUNET_GNSRECORD_Data *rd)
2029 {
2030  struct ZoneMonitor *zm = cls;
2031 
2032  GNUNET_assert (0 != seq);
2033  zm->seq = seq;
2034  GNUNET_assert (NULL != name);
2035  GNUNET_STATISTICS_update (statistics,
2036  "Monitor notifications sent",
2037  1,
2038  GNUNET_NO);
2039  zm->limit--;
2040  zm->iteration_cnt--;
2041  send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd);
2042  if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2043  {
2044  /* We are done with the current iteration batch, AND the
2045  client would right now accept more, so go again! */
2046  GNUNET_assert (NULL == zm->task);
2048  }
2049 }
2050 
2051 
2058 static void
2059 handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg)
2060 {
2061  struct NamestoreClient *nc = cls;
2062  struct ZoneMonitor *zm;
2063 
2064  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n");
2065  zm = GNUNET_new (struct ZoneMonitor);
2066  zm->nc = nc;
2067  zm->zone = zis_msg->zone;
2068  zm->limit = 1;
2069  zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2070  GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2073  GNUNET_notification_context_add (monitor_nc, nc->mq);
2074  if (zm->in_first_iteration)
2076  else
2077  monitor_sync (zm);
2078 }
2079 
2080 
2086 static void
2088 {
2089  struct ZoneMonitor *zm = cls;
2090  int ret;
2091 
2092  zm->task = NULL;
2093  GNUNET_assert (0 == zm->iteration_cnt);
2094  if (zm->limit > 16)
2095  zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2096  else
2097  zm->iteration_cnt = zm->limit; /* use it all */
2098  ret = GSN_database->iterate_records (GSN_database->cls,
2100  &zm->zone))
2101  ? NULL
2102  : &zm->zone,
2103  zm->seq,
2104  zm->iteration_cnt,
2106  zm);
2107  if (GNUNET_SYSERR == ret)
2108  {
2110  return;
2111  }
2112  if (GNUNET_NO == ret)
2113  {
2114  /* empty zone */
2115  monitor_sync (zm);
2116  return;
2117  }
2118 }
2119 
2120 
2127 static void
2128 handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2129 {
2130  struct NamestoreClient *nc = cls;
2131  struct ZoneMonitor *zm;
2132  uint64_t inc;
2133 
2134  inc = GNUNET_ntohll (nm->limit);
2136  "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2137  (unsigned long long) inc);
2138  for (zm = monitor_head; NULL != zm; zm = zm->next)
2139  if (zm->nc == nc)
2140  break;
2141  if (NULL == zm)
2142  {
2143  GNUNET_break (0);
2145  return;
2146  }
2148  if (zm->limit + inc < zm->limit)
2149  {
2150  GNUNET_break (0);
2152  return;
2153  }
2154  zm->limit += inc;
2155  if ((zm->in_first_iteration) && (zm->limit == inc))
2156  {
2157  /* We are still iterating, and the previous iteration must
2158  have stopped due to the client's limit, so continue it! */
2159  GNUNET_assert (NULL == zm->task);
2161  }
2162  GNUNET_assert (zm->iteration_cnt <= zm->limit);
2163  if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2164  {
2165  monitor_unblock (zm);
2166  }
2167  else if (GNUNET_YES == zm->sa_waiting)
2168  {
2169  if (NULL != zm->sa_wait_warning)
2172  zm->sa_wait_warning =
2175  zm);
2176  }
2177 }
2178 
2179 
2187 static void
2188 run (void *cls,
2189  const struct GNUNET_CONFIGURATION_Handle *cfg,
2191 {
2192  char *database;
2193 
2194  (void) cls;
2195  (void) service;
2196  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2197  cache_keys =
2198  GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS");
2200  GNUNET_CONFIGURATION_get_value_yesno (cfg, "namecache", "DISABLE");
2201  GSN_cfg = cfg;
2202  monitor_nc = GNUNET_notification_context_create (1);
2204  {
2205  namecache = GNUNET_NAMECACHE_connect (cfg);
2206  GNUNET_assert (NULL != namecache);
2207  }
2208  /* Loading database plugin */
2210  "namestore",
2211  "database",
2212  &database))
2213  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2214 
2215  GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2216  GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2217  GNUNET_free (database);
2218  statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2220  if (NULL == GSN_database)
2221  {
2223  "Could not load database backend `%s'\n",
2224  db_lib_name);
2226  return;
2227  }
2228 }
2229 
2230 
2235  "namestore",
2237  &run,
2240  NULL,
2241  GNUNET_MQ_hd_var_size (record_store,
2243  struct RecordStoreMessage,
2244  NULL),
2245  GNUNET_MQ_hd_var_size (record_lookup,
2247  struct LabelLookupMessage,
2248  NULL),
2251  struct ZoneToNameMessage,
2252  NULL),
2256  NULL),
2257  GNUNET_MQ_hd_fixed_size (iteration_next,
2259  struct ZoneIterationNextMessage,
2260  NULL),
2261  GNUNET_MQ_hd_fixed_size (iteration_stop,
2263  struct ZoneIterationStopMessage,
2264  NULL),
2265  GNUNET_MQ_hd_fixed_size (monitor_start,
2267  struct ZoneMonitorStartMessage,
2268  NULL),
2269  GNUNET_MQ_hd_fixed_size (monitor_next,
2271  struct ZoneMonitorNextMessage,
2272  NULL),
2274 
2275 
2276 /* end of gnunet-service-namestore.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int send_end
Set to GNUNET_YES if the last iteration exhausted the limit set by the client and we should send the ...
struct GNUNET_IDENTITY_PrivateKey zone
Zone the cache entry is for.
struct CacheOperation * next
Kept in a DLL.
static void handle_iteration_next(void *cls, const struct ZoneIterationNextMessage *zis_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message.
struct GNUNET_IDENTITY_PrivateKey private_key
The private key of the authority.
Definition: namestore.h:179
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE.
Definition: namestore.h:110
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE.
Definition: namestore.h:63
struct GNUNET_NAMECACHE_Handle * GNUNET_NAMECACHE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namecache service.
static char * db_lib_name
Name of the database plugin.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:75
static struct GNUNET_NotificationContext * monitor_nc
Notification context shared by all monitors.
struct GNUNET_MQ_Handle * mq
Message queue for transmission to client.
#define GNUNET_GNSRECORD_TYPE_NICK
GNS nick names.
Start monitoring a zone.
Definition: namestore.h:298
char * GNUNET_GNSRECORD_string_to_lowercase(const char *src)
Convert a UTF-8 string to UTF-8 lowercase.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
uint32_t label_len
Length of the name.
Definition: namestore.h:132
struct NamestoreClient * nc
Namestore client.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE
Service to client: result of zone-to-name lookup.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT
Client to service: I am now ready for the next (set of) monitor events.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
Handle to a service.
Definition: service.c:116
Ask for next result of zone iteration for the given operation.
Definition: namestore.h:362
struct GNUNET_NAMECACHE_QueueEntry * qe
Handle to namecache queue.
uint16_t rd_len
Length of serialized record data.
Definition: namestore.h:163
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
struct NamestoreClient * nc
Namestore client which intiated this zone monitor.
uint64_t limit
Number of results left to be returned in this iteration.
uint64_t iteration_cnt
How many more requests may we receive from the iterator before it is at the limit we gave it...
static void monitor_iterate_cb(void *cls, uint64_t seq, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
A GNUNET_NAMESTORE_RecordIterator for monitors.
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
struct ZoneMonitor * prev
Previous element in the DLL.
uint32_t r_id
Request ID in NBO.
Definition: namestore.h:51
uint16_t rd_count
Number of records contained.
Definition: namestore.h:168
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Start a zone iteration for the given zone.
Definition: namestore.h:345
struct GNUNET_IDENTITY_PrivateKey zone
Monitored zone.
static struct ZoneMonitor * monitor_head
First active zone monitor.
uint64_t seq
Last sequence number in the zone iteration used to address next result of the zone iteration in the s...
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME.
Definition: namestore.h:196
uint16_t name_len
Length of the name.
Definition: namestore.h:223
A private key for an identity as per LSD0001.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
struct ZoneMonitor * zm_pos
Next zone monitor that still needs to be notified about this PUT.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static void handle_monitor_next(void *cls, const struct ZoneMonitorNextMessage *nm)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
struct GNUNET_TIME_Absolute sa_waiting_start
Since when are we blocked on this monitor?
int16_t res
result in NBO: GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error ...
Definition: namestore.h:239
static struct GNUNET_NAMESTORE_ZoneMonitor * zm
Monitor handle.
This is a supplemental record.
struct GNUNET_IDENTITY_PrivateKey private_key
The private key of the authority.
Definition: namestore.h:286
size_t data_size
Number of bytes in data.
struct StoreActivity * next
Kept in a DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static struct CacheOperation * cop_head
Head of cop DLL.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
Service to client: end of list of results.
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static struct NickCache nick_cache[16]
We cache nick records to reduce DB load.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
Handle for the service.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
struct GNUNET_IDENTITY_PrivateKey zone
Zone key.
Definition: namestore.h:355
#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP
Client to service: lookup label.
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:160
uint64_t abs_value_us
The actual value.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP
Client to service: stop iterating.
uint16_t reserved
always zero (for alignment)
Definition: namestore.h:88
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create(const struct GNUNET_IDENTITY_PrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records.
int success
Set to GNUNET_OK on success, GNUNET_SYSERR on error.
static void run_zone_iteration_round(struct ZoneIteration *zi, uint64_t limit)
Perform the next round of the zone iteration.
Entry in list of cached nick resolutions.
struct ZoneIteration * op_head
Head of the DLL of Zone iteration operations in progress initiated by this client.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
uint16_t name_len
Name length.
Definition: namestore.h:266
static int disable_namecache
Use the namecache? Doing so creates additional cryptographic operations whenever we touch a record...
#define NC_SIZE
Size of the cache used by get_nick_record()
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:269
common internal definitions for namestore service
Handle to a client that is connected to a service.
Definition: service.c:250
uint16_t rd_count
Number of records contained.
Definition: namestore.h:233
void * cls
Closure to pass to all plugin functions.
uint64_t seq
Last sequence number in the zone iteration used to address next result of the zone iteration in the s...
int32_t op_result
GNUNET_SYSERR on failure, GNUNET_OK on success
Definition: namestore.h:115
struct GNUNET_MessageHeader header
header.type will be GNUNET_MESSAGE_TYPE_NAMESTORE_* header.size will be message size ...
Definition: namestore.h:46
uint64_t limit
Number of records to return to the iterator in one shot (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_M...
Definition: namestore.h:338
static void monitor_iteration_next(void *cls)
Obtain the next datum during the zone monitor&#39;s zone initial iteration.
struct GNUNET_IDENTITY_PrivateKey zone
The private key of the zone to look up in.
Definition: namestore.h:137
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
uint32_t rid
Client&#39;s request ID.
static int check_record_lookup(void *cls, const struct LabelLookupMessage *ll_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message.
struct GNUNET_IDENTITY_PrivateKey zone
Zone key.
Definition: namestore.h:314
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
uint16_t rd_len
Length of serialized record data.
Definition: namestore.h:78
const void * data
Binary value stored in the DNS record.
static struct ZoneMonitor * monitor_tail
Last active zone monitor.
struct GNUNET_IDENTITY_PrivateKey zone
Key of the zone we are iterating over.
A namestore client.
uint16_t rd_count
Number of records contained.
Definition: namestore.h:276
static const struct GNUNET_IDENTITY_PrivateKey * zone_key
Private key of the zone.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE
Client to service: store records (as authority)
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
struct GNUNET_TIME_Absolute last_used
Timestamp when this cache entry was used last.
static int check_record_store(void *cls, const struct RecordStoreMessage *rp_msg)
Checks a GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message.
struct ZoneIteration * zi
The zone iteration handle.
static void zone_iterate_proc(void *cls, uint64_t seq, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process results for zone iteration from database.
#define MONITOR_STALL_WARN_DELAY
If a monitor takes more than 1 minute to process an event, print a warning.
uint64_t expiration_time
Expiration time for the DNS record.
Closure for lookup_it().
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
static void continue_store_activity(struct StoreActivity *sa)
Continue processing the sa.
GNUNET_SERVICE_MAIN("namestore", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(record_store, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, struct RecordStoreMessage, NULL), GNUNET_MQ_hd_var_size(record_lookup, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP, struct LabelLookupMessage, NULL), GNUNET_MQ_hd_fixed_size(zone_to_name, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, struct ZoneToNameMessage, NULL), GNUNET_MQ_hd_fixed_size(iteration_start, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, struct ZoneIterationStartMessage, NULL), GNUNET_MQ_hd_fixed_size(iteration_next, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, struct ZoneIterationNextMessage, NULL), GNUNET_MQ_hd_fixed_size(iteration_stop, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, struct ZoneIterationStopMessage, NULL), GNUNET_MQ_hd_fixed_size(monitor_start, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START, struct ZoneMonitorStartMessage, NULL), GNUNET_MQ_hd_fixed_size(monitor_next, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT, struct ZoneMonitorNextMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
struct NamestoreClient * nc
Which client triggered the store activity?
struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create2(const struct GNUNET_IDENTITY_PrivateKey *pkey, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records, cache derived public key (also keeps the private key in static memory...
struct GNUNET_IDENTITY_PrivateKey zone
Private key of the zone.
static void finish_cache_operation(void *cls, int32_t success, const char *emsg)
Cache operation complete, clean up.
Stop zone iteration for the given operation.
Definition: namestore.h:381
static void lookup_it(void *cls, uint64_t seq, const struct GNUNET_IDENTITY_PrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called by the namestore plugin when we are trying to lookup a record as part of handle_recor...
static void monitor_sync(struct ZoneMonitor *zm)
Send &#39;sync&#39; message to zone monitor, we&#39;re now in sync.
struct StoreActivity * prev
Kept in a DLL.
uint16_t name_len
Name length.
Definition: namestore.h:73
uint64_t limit
Current limit of how many more messages we are allowed to queue to this monitor.
unsigned int cache_ops
Number of pending cache operations triggered by this zone iteration which we need to wait for before ...
static void handle_record_store(void *cls, const struct RecordStoreMessage *rp_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message.
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
int in_first_iteration
Are we (still) in the initial iteration pass?
uint16_t name_len
Name length.
Definition: namestore.h:158
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_key_get_public(const struct GNUNET_IDENTITY_PrivateKey *privkey, struct GNUNET_IDENTITY_PublicKey *key)
Retrieves the public key representation of a private key.
Definition: identity_api.c:175
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2408
static void handle_zone_to_name_it(void *cls, uint64_t seq, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Zone to name iterator.
This is a private record of this peer and it should thus not be handed out to other peers...
static void handle_monitor_start(void *cls, const struct ZoneMonitorStartMessage *zis_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message.
struct ZoneIteration * next
Next element in the DLL.
struct GNUNET_SERVICE_Client * client
The client.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namecache.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2325
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START.
Definition: namestore.h:350
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
uint16_t rd_count
Number of records contained.
Definition: namestore.h:83
static void send_lookup_response(struct NamestoreClient *nc, uint32_t request_id, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Generate a struct LookupNameResponseMessage and send it to the given client using the given notificat...
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Add a client to our list of active clients.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Returns the expiration time of the given block of records.
struct GNUNET_SCHEDULER_Task * task
Task active during initial iteration.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME
Client to service: "reverse" lookup for zone name based on zone key.
char * conv_name
Label nicely canonicalized (lower case).
struct GNUNET_IDENTITY_PrivateKey private_key
The private key of the authority.
Definition: namestore.h:93
#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START
Client to service: please start iteration; receives "GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPON...
int GNUNET_get_log_call_status(int caller_level, const char *comp, const char *file, const char *function, int line)
Decides whether a particular logging call should or should not be allowed to be made.
uint32_t offset
Offset of the zone iteration used to address next result of the zone iteration in the store...
int(* lookup_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Lookup records in the datastore for which we are the authority.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT
Client to service: next record(s) in iteration please.
int(* zone_to_name)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const struct GNUNET_IDENTITY_PublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Look for an existing PKEY delegation record for a given public key.
struct ZoneIteration * zi
Zone iteration to call zone_iteration_done_client_continue() for if applicable, can be NULL...
uint32_t request_id
The operation id for the zone iteration in the response for the client.
unsigned int res_rd_count
FIXME.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct StoreActivity * sa_tail
Tail of DLL of monitor-blocked store activities.
uint16_t found
Was the label found in the database?? GNUNET_YES or GNUNET_NO.
Definition: namestore.h:174
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
uint16_t rd_len
Length of serialized record data.
Definition: namestore.h:271
static void iteration_start()
Information for an ongoing handle_record_store() operation.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT.
Definition: namestore.h:261
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
uint32_t iterate_first
GNUNET_YES to first iterate over all records, GNUNET_NO to only monitor changes.o ...
Definition: namestore.h:309
#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
Service to client: lookup label.
static void handle_zone_to_name(void *cls, const struct ZoneToNameMessage *ztn_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:121
#define GNUNET_LOG_CALL_STATUS
static struct GNUNET_GNSRECORD_Data * get_nick_record(const struct GNUNET_IDENTITY_PrivateKey *zone)
Return the NICK record for the zone (if it exists).
struct CacheOperation * prev
Kept in a DLL.
Ask for next result of zone iteration for the given operation.
Definition: namestore.h:321
Handle to a message queue.
Definition: mq.c:85
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
Definition: namestore.h:218
Store a record to the namestore (as authority).
Definition: namestore.h:58
static const struct GNUNET_IDENTITY_PrivateKey zero
Public key of all zeros.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Process namestore requests.
struct ZoneIteration * prev
Previous element in the DLL.
Context for record remove operations passed from handle_zone_to_name to handle_zone_to_name_it as clo...
Respone for zone to name lookup.
Definition: namestore.h:213
struct GNUNET_GNSRECORD_Data * nick
FIXME.
static const struct GNUNET_CONFIGURATION_Handle * GSN_cfg
Configuration handle.
int(* store_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Store a record in the datastore for which we are the authority.
An identity key as per LSD0001.
static void send_store_response(struct NamestoreClient *nc, int res, uint32_t rid)
Send response to the store request to the client.
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE.
Definition: namestore.h:153
static void lookup_nick_it(void *cls, uint64_t seq, const struct GNUNET_IDENTITY_PrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called with the records for the GNUNET_GNS_EMPTY_LABEL_AT label in the zone.
uint32_t record_type
Type of the GNS/DNS record.
static void free_store_activity(struct StoreActivity *sa)
Release memory used by sa.
struct GNUNET_IDENTITY_PrivateKey zone
The private key of the zone that contained the name.
Definition: namestore.h:244
struct ZoneIteration * op_tail
Tail of the DLL of Zone iteration operations in progress initiated by this client.
struct GNUNET_GNSRECORD_Data * nick
The nick to add to the records.
configuration data
Response to a record storage request.
Definition: namestore.h:105
const char * name
static struct StoreActivity * sa_head
Head of DLL of monitor-blocked store activities.
static struct GNUNET_NAMESTORE_PluginFunctions * GSN_database
Database handle.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:263
A namestore iteration operation.
Pending operation on the namecache.
#define MAX_NAME_LEN
Maximum length of any name, including 0-termination.
Definition: namecache.h:33
struct GNUNET_IDENTITY_PublicKey value_zone
The public key of the target zone.
Definition: namestore.h:206
Connection to the NAMECACHE service.
Definition: namecache_api.c:94
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
Generic namestore message with op id.
Definition: namestore.h:40
#define GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC
Service to client: you&#39;re now in sync.
#define GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START
Client to service: start monitoring (yields sequence of "ZONE_ITERATION_RESPONSES" — forever)...
uint16_t rd_len
Length of serialized record data.
Definition: namestore.h:228
struct ZoneMonitor * next
Next element in the DLL.
void GNUNET_NAMECACHE_disconnect(struct GNUNET_NAMECACHE_Handle *h)
Disconnect from the namecache service (and free associated resources).
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP.
Definition: namestore.h:127
static void cache_nick(const struct GNUNET_IDENTITY_PrivateKey *zone, const struct GNUNET_GNSRECORD_Data *nick)
Add entry to the cache for zone and nick.
Lookup a name for a zone hash.
Definition: namestore.h:191
const struct RecordStoreMessage * rsm
Copy of the original store message (as data fields in rd will point into it!).
Lookup a label.
Definition: namestore.h:122
static int zone_to_name(void *cls, const struct GNUNET_HashCode *key, void *value)
static void cleanup_task(void *cls)
Task run during shutdown.
struct GNUNET_IDENTITY_PrivateKey zone
The private key of the zone to look up in.
Definition: namestore.h:201
Header for all communications.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:376
struct NamestoreClient * nc
Client to notify about the result, can be NULL.
Time for absolute times used by GNUnet, in microseconds.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:137
An QueueEntry used to store information for a pending NAMECACHE record operation. ...
Definition: namecache_api.c:47
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:217
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:355
#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
Service to client: here is a (plaintext) record you requested.
static struct GNUNET_NAMECACHE_Handle * namecache
Namecache handle.
Record is returned from the namestore (as authority).
Definition: namestore.h:256
uint64_t limit
Number of records to return to the iterator in one shot (before GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_IT...
Definition: namestore.h:374
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
This expiration time of the record is a relative time (not an absolute time).
int(* iterate_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, uint64_t serial, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Iterate over the results for a particular zone in the datastore.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:604
static int cache_keys
Optimize block insertion by caching map of private keys to public keys in memory? ...
static void refresh_block(struct NamestoreClient *nc, struct ZoneIteration *zi, uint32_t rid, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We just touched the plaintext information about a name in our zone; refresh the corresponding (encryp...
struct GNUNET_SCHEDULER_Task * sa_wait_warning
Task to warn about slow monitors.
static void merge_with_nick_records(const struct GNUNET_GNSRECORD_Data *nick_rd, unsigned int rd2_length, const struct GNUNET_GNSRECORD_Data *rd2, unsigned int *rdc_res, struct GNUNET_GNSRECORD_Data **rd_res)
Merge the nick record nick_rd with the rest of the record set given in rd2.
static void zone_iteration_done_client_continue(struct ZoneIteration *zi)
Function called once we are done with the zone iteration and allow the zone iteration client to send ...
uint32_t data
The data value.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone key to a string (for printing debug messages).
int sa_waiting
Is there a store activity waiting for this monitor? We only raise the flag when it happens and search...
struct NamestoreClient * nc
Namestore client which intiated this zone iteration.
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT.
Definition: namestore.h:367
struct returned by the initialization function of the plugin
static struct CacheOperation * cop_tail
Tail of cop DLL.
static void handle_iteration_start(void *cls, const struct ZoneIterationStartMessage *zis_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2244
static void handle_record_lookup(void *cls, const struct LabelLookupMessage *ll_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message.
static void warn_monitor_slow(void *cls)
Print a warning that one of our monitors is no longer reacting.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct GNUNET_NAMESTORE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP.
Definition: namestore.h:386
static void monitor_unblock(struct ZoneMonitor *zm)
Function called when the monitor is ready for more data, and we should thus unblock PUT operations th...
static void handle_iteration_stop(void *cls, const struct ZoneIterationStopMessage *zis_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message.
Lookup a label.
Definition: namestore.h:148
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_GNSRECORD_Data * rd
Cached record data.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
A namestore monitor.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
Context for record remove operations passed from run_zone_iteration_round to zone_iterate_proc as clo...
uint32_t rid
Request id (to be used in the response to the client).
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
Service to client: result of store operation.