GNUnet  0.10.x
gnunet-service-nse.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2011, 2012, 2013, 2016 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 
38 #include "platform.h"
39 #include <math.h>
40 #include "gnunet_util_lib.h"
41 #include "gnunet_constants.h"
42 #include "gnunet_protocols.h"
43 #include "gnunet_signatures.h"
45 #include "gnunet_core_service.h"
46 #include "gnunet_nse_service.h"
47 #if ENABLE_NSE_HISTOGRAM
49 #endif
50 #include "nse.h"
51 #include <gcrypt.h>
52 
53 
58 #define USE_RANDOM_DELAYS GNUNET_YES
59 
63 #define DEBUG_NSE GNUNET_NO
64 
68 #define HISTORY_SIZE 64
69 
74 #define NSE_PRIORITY \
75  (GNUNET_MQ_PRIO_BACKGROUND | GNUNET_MQ_PREF_UNRELIABLE | \
76  GNUNET_MQ_PREF_CORK_ALLOWED)
77 
78 #if FREEBSD
79 #define log2(a) (log(a) / log(2))
80 #endif
81 
85 static unsigned long long nse_work_required;
86 
91 
96 
97 #if ENABLE_NSE_HISTOGRAM
98 
102 struct GNUNET_CLIENT_TestHandle *logger_test;
103 
107 static struct GNUNET_TESTBED_LOGGER_Handle *lh;
108 
112 static struct GNUNET_BIO_WriteHandle *histogram;
113 
114 #endif
115 
116 
120 struct NSEPeerEntry {
125 
129  const struct GNUNET_PeerIdentity *id;
130 
135 
142 
143 #if ENABLE_NSE_HISTOGRAM
144 
147  unsigned int received_messages;
148 
152  unsigned int transmitted_messages;
153 
157  unsigned int last_transmitted_size;
158 #endif
159 };
160 
161 
163 
173  struct GNUNET_MessageHeader header;
174 
178  uint32_t hop_count GNUNET_PACKED;
179 
184 
189  struct GNUNET_TIME_AbsoluteNBO timestamp;
190 
197 
201  struct GNUNET_PeerIdentity origin;
202 
206  uint64_t proof_of_work GNUNET_PACKED;
207 
212 };
214 
218 static const struct GNUNET_CONFIGURATION_Handle *cfg;
219 
224 
229 
234 
239 static double current_size_estimate;
240 
245 static double current_std_dev = NAN;
246 
250 static uint32_t hop_count_max;
251 
256 
261 
265 static unsigned int estimate_index;
266 
270 static unsigned int estimate_count;
271 
276 
281 
286 
291 
296 
301 
306 
310 static uint64_t my_proof;
311 
312 
319 static void
321 {
322  double mean;
323  double sum;
324  double std_dev;
325  double variance;
326  double val;
327  double nsize;
328 
329 #define WEST 1
330  /* Weighted incremental algorithm for stddev according to West (1979) */
331 #if WEST
332  double sumweight;
333  double weight;
334  double q;
335  double r;
336  double temp;
337 
338  mean = 0.0;
339  sum = 0.0;
340  sumweight = 0.0;
341  variance = 0.0;
342  for (unsigned int i = 0; i < estimate_count; i++)
343  {
344  unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE;
345 
346  val = htonl(size_estimate_messages[j].matching_bits);
347  weight = estimate_count + 1 - i;
348 
349  temp = weight + sumweight;
350  q = val - mean;
351  r = q * weight / temp;
352  mean += r;
353  sum += sumweight * q * r;
354  sumweight = temp;
355  }
356  if (estimate_count > 0)
357  variance = (sum / sumweight) * estimate_count / (estimate_count - 1.0);
358 #else
359  /* trivial version for debugging */
360  double vsq;
361 
362  /* non-weighted trivial version */
363  sum = 0.0;
364  vsq = 0.0;
365  variance = 0.0;
366  mean = 0.0;
367 
368  for (unsigned int i = 0; i < estimate_count; i++)
369  {
370  unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE;
371 
372  val = htonl(size_estimate_messages[j].matching_bits);
373  sum += val;
374  vsq += val * val;
375  }
376  if (0 != estimate_count)
377  {
378  mean = sum / estimate_count;
379  variance = (vsq - mean * sum) /
380  (estimate_count - 1.0); // terrible for numerical stability...
381  }
382 #endif
383  if (variance >= 0)
384  std_dev = sqrt(variance);
385  else
386  std_dev = variance; /* must be infinity due to estimate_count == 0 */
387  current_std_dev = std_dev;
388  current_size_estimate = mean;
389 
390  em->header.size = htons(sizeof(struct GNUNET_NSE_ClientMessage));
392  em->reserved = htonl(0);
394  {
395  double se = mean - 0.332747;
396  unsigned int j = GNUNET_CONTAINER_multipeermap_size(peers);
397  if (0 == j)
398  j = 1; /* Avoid log2(0); can only happen if CORE didn't report
399  connection to self yet */
400  nsize = log2(j);
401  em->size_estimate = GNUNET_hton_double(GNUNET_MAX(se, nsize));
402  em->std_deviation = GNUNET_hton_double(std_dev);
403  GNUNET_STATISTICS_set(stats,
404  "# nodes in the network (estimate)",
405  (uint64_t)pow(2, GNUNET_MAX(se, nsize)),
406  GNUNET_NO);
407  }
408 }
409 
410 
420 static void
421 handle_start(void *cls, const struct GNUNET_MessageHeader *message)
422 {
423  struct GNUNET_SERVICE_Client *client = cls;
424  struct GNUNET_MQ_Handle *mq;
425  struct GNUNET_NSE_ClientMessage em;
426  struct GNUNET_MQ_Envelope *env;
427 
428  (void)message;
429  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received START message from client\n");
430  mq = GNUNET_SERVICE_client_get_mq(client);
433  env = GNUNET_MQ_msg_copy(&em.header);
434  GNUNET_MQ_send(mq, env);
436 }
437 
438 
445 static double
447 {
448  /* Calculated as: S + f/2 - (f / pi) * (atan(x - p')) */
449  // S is next_timestamp (ignored in return value)
450  // f is frequency (gnunet_nse_interval)
451  // x is matching_bits
452  // p' is current_size_estimate
453  return ((double)gnunet_nse_interval.rel_value_us / (double)2.0) -
455  atan(matching_bits - current_size_estimate));
456 }
457 
458 
465 static struct GNUNET_TIME_Relative
467 {
468 #if USE_RANDOM_DELAYS
469  struct GNUNET_TIME_Relative ret;
470  uint32_t i;
471  double d;
472 
474  i = (uint32_t)(d / (double)(hop_count_max + 1));
475  ret.rel_value_us = i;
477  "Randomizing flood using latencies up to %s\n",
479  ret.rel_value_us =
481  return ret;
482 #else
483  return GNUNET_TIME_UNIT_ZERO;
484 #endif
485 }
486 
487 
495 static void
496 pow_hash(const void *buf, size_t buf_len, struct GNUNET_HashCode *result)
497 {
498  GNUNET_break(
499  0 == gcry_kdf_derive(buf,
500  buf_len,
501  GCRY_KDF_SCRYPT,
502  1 /* subalgo */,
503  "gnunet-proof-of-work",
504  strlen("gnunet-proof-of-work"),
505  2 /* iterations; keep cost of individual op small */,
506  sizeof(struct GNUNET_HashCode),
507  result));
508 }
509 
510 
518 static uint32_t
520  const struct GNUNET_PeerIdentity *id)
521 {
522  struct GNUNET_HashCode timestamp_hash;
523  struct GNUNET_HashCode pid_hash;
524 
525  GNUNET_CRYPTO_hash(&timestamp.abs_value_us,
526  sizeof(timestamp.abs_value_us),
527  &timestamp_hash);
528  GNUNET_CRYPTO_hash(id, sizeof(struct GNUNET_PeerIdentity), &pid_hash);
529  return GNUNET_CRYPTO_hash_matching_bits(&timestamp_hash, &pid_hash);
530 }
531 
532 
541 static struct GNUNET_TIME_Relative
542 get_transmit_delay(int round_offset)
543 {
544  struct GNUNET_TIME_Relative ret;
545  struct GNUNET_TIME_Absolute tgt;
546  double dist_delay;
547  uint32_t matching_bits;
548 
549  switch (round_offset)
550  {
551  case -1:
552  /* previous round is randomized between 0 and 50 ms */
553 #if USE_RANDOM_DELAYS
554  ret.rel_value_us =
556 #else
557  ret = GNUNET_TIME_UNIT_ZERO;
558 #endif
560  "Transmitting previous round behind schedule in %s\n",
562  return ret;
563 
564  case 0:
565  /* current round is based on best-known matching_bits */
566  matching_bits =
567  ntohl(size_estimate_messages[estimate_index].matching_bits);
568  dist_delay = get_matching_bits_delay(matching_bits);
569  dist_delay += get_delay_randomization(matching_bits).rel_value_us;
570  ret.rel_value_us = (uint64_t)dist_delay;
572  "For round %s, delay for %u matching bits is %s\n",
574  (unsigned int)matching_bits,
576  /* now consider round start time and add delay to it */
579  }
580  GNUNET_break(0);
582 }
583 
584 
590 static void
592 {
593  struct NSEPeerEntry *peer_entry = cls;
594  unsigned int idx;
595  struct GNUNET_MQ_Envelope *env;
596 
597  peer_entry->transmit_task = NULL;
598  idx = estimate_index;
599  if (GNUNET_NO == peer_entry->previous_round)
600  {
601  idx = (idx + HISTORY_SIZE - 1) % HISTORY_SIZE;
602  peer_entry->previous_round = GNUNET_YES;
603  peer_entry->transmit_task =
606  peer_entry);
607  }
608  if ((0 == ntohl(size_estimate_messages[idx].hop_count)) &&
609  (NULL != proof_task))
610  {
612  "# flood messages not generated (no proof yet)",
613  1,
614  GNUNET_NO);
615  return;
616  }
617  if (0 == ntohs(size_estimate_messages[idx].header.size))
618  {
620  "# flood messages not generated (lack of history)",
621  1,
622  GNUNET_NO);
623  return;
624  }
626  "In round %s, sending to `%s' estimate with %u bits\n",
629  size_estimate_messages[idx].timestamp)),
630  GNUNET_i2s(peer_entry->id),
631  (unsigned int)ntohl(size_estimate_messages[idx].matching_bits));
632  if (0 == ntohl(size_estimate_messages[idx].hop_count))
633  GNUNET_STATISTICS_update(stats, "# flood messages started", 1, GNUNET_NO);
635  "# flood messages transmitted",
636  1,
637  GNUNET_NO);
638 #if ENABLE_NSE_HISTOGRAM
639  peer_entry->transmitted_messages++;
640  peer_entry->last_transmitted_size =
641  ntohl(size_estimate_messages[idx].matching_bits);
642 #endif
643  env = GNUNET_MQ_msg_copy(&size_estimate_messages[idx].header);
644  GNUNET_MQ_send(peer_entry->mq, env);
645 }
646 
647 
654 static void
656 {
657  struct GNUNET_NSE_ClientMessage em;
658 
661 }
662 
663 
671 static void
672 setup_flood_message(unsigned int slot, struct GNUNET_TIME_Absolute ts)
673 {
674  struct GNUNET_NSE_FloodMessage *fm;
675  uint32_t matching_bits;
676 
677  matching_bits = get_matching_bits(ts, &my_identity);
678  fm = &size_estimate_messages[slot];
679  fm->header.size = htons(sizeof(struct GNUNET_NSE_FloodMessage));
681  fm->hop_count = htonl(0);
683  fm->purpose.size =
684  htonl(sizeof(struct GNUNET_NSE_FloodMessage) -
685  sizeof(struct GNUNET_MessageHeader) - sizeof(uint32_t) -
686  sizeof(struct GNUNET_CRYPTO_EddsaSignature));
687  fm->matching_bits = htonl(matching_bits);
689  fm->origin = my_identity;
690  fm->proof_of_work = my_proof;
691  if (nse_work_required > 0)
693  &fm->purpose,
694  &fm->signature));
695  else
696  memset(&fm->signature, 0, sizeof(fm->signature));
697 }
698 
699 
709 static int
711  const struct GNUNET_PeerIdentity *key,
712  void *value)
713 {
714  struct NSEPeerEntry *peer_entry = value;
715  struct GNUNET_TIME_Relative delay;
716 
717  (void)cls;
718  (void)key;
719  if (NULL != peer_entry->transmit_task)
720  {
722  peer_entry->previous_round = GNUNET_NO;
723  }
724 #if ENABLE_NSE_HISTOGRAM
725  if (peer_entry->received_messages > 1)
727  "# extra messages",
728  peer_entry->received_messages - 1,
729  GNUNET_NO);
730  peer_entry->transmitted_messages = 0;
731  peer_entry->last_transmitted_size = 0;
732  peer_entry->received_messages = 0;
733 #endif
734  delay =
735  get_transmit_delay((GNUNET_NO == peer_entry->previous_round) ? -1 : 0);
736  peer_entry->transmit_task =
737  GNUNET_SCHEDULER_add_delayed(delay, &transmit_task_cb, peer_entry);
738  return GNUNET_OK;
739 }
740 
741 
747 static void
749 {
750  struct GNUNET_TIME_Relative offset;
751 
752  (void)cls;
753  flood_task = NULL;
755  if (0 != offset.rel_value_us)
756  {
757  /* somehow run early, delay more */
758  flood_task =
760  return;
761  }
764  estimate_count++;
771  ntohl(next_message.matching_bits)))
772  {
773  /* we received a message for this round way early, use it! */
776  htonl(1 + ntohl(next_message.hop_count));
777  }
778  else
780  next_message.matching_bits = htonl(0); /* reset for 'next' round */
781  hop_count_max = 0;
782  for (unsigned int i = 0; i < HISTORY_SIZE; i++)
783  hop_count_max =
784  GNUNET_MAX(ntohl(size_estimate_messages[i].hop_count), hop_count_max);
786  flood_task =
788 }
789 
790 
797 static unsigned int
799 {
800  unsigned int hash_count;
801 
802  hash_count = 0;
803  while (0 == GNUNET_CRYPTO_hash_get_bit(hash, hash_count))
804  hash_count++;
805  return hash_count;
806 }
807 
808 
817 static int
819  uint64_t val)
820 {
821  char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) +
822  sizeof(val)] GNUNET_ALIGN;
823  struct GNUNET_HashCode result;
824 
825  GNUNET_memcpy(buf, &val, sizeof(val));
826  GNUNET_memcpy(&buf[sizeof(val)],
827  pkey,
828  sizeof(struct GNUNET_CRYPTO_EddsaPublicKey));
829  pow_hash(buf, sizeof(buf), &result);
830  return (count_leading_zeroes(&result) >= nse_work_required) ? GNUNET_YES
831  : GNUNET_NO;
832 }
833 
834 
838 static void
840 {
841  char *proof;
842 
843  if (GNUNET_OK !=
844  GNUNET_CONFIGURATION_get_value_filename(cfg, "NSE", "PROOFFILE", &proof))
845  return;
846  if (sizeof(my_proof) != GNUNET_DISK_fn_write(proof,
847  &my_proof,
848  sizeof(my_proof),
852  GNUNET_free(proof);
853 }
854 
855 
861 static void
862 find_proof(void *cls)
863 {
864 #define ROUND_SIZE 10
865  uint64_t counter;
866  char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) +
867  sizeof(uint64_t)] GNUNET_ALIGN;
868  struct GNUNET_HashCode result;
869  unsigned int i;
870 
871  (void)cls;
872  proof_task = NULL;
873  GNUNET_memcpy(&buf[sizeof(uint64_t)],
874  &my_identity,
875  sizeof(struct GNUNET_PeerIdentity));
876  i = 0;
877  counter = my_proof;
878  while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
879  {
880  GNUNET_memcpy(buf, &counter, sizeof(uint64_t));
881  pow_hash(buf, sizeof(buf), &result);
882  if (nse_work_required <= count_leading_zeroes(&result))
883  {
884  my_proof = counter;
886  "Proof of work found: %llu!\n",
887  (unsigned long long)GNUNET_ntohll(counter));
888  write_proof();
890  return;
891  }
892  counter++;
893  i++;
894  }
895  if (my_proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE))
896  {
898  "Testing proofs currently at %llu\n",
899  (unsigned long long)counter);
900  /* remember progress every 100 rounds */
901  my_proof = counter;
902  write_proof();
903  }
904  else
905  {
906  my_proof = counter;
907  }
908  proof_task =
911  &find_proof,
912  NULL);
913 }
914 
915 
925 static int
926 verify_message_crypto(const struct GNUNET_NSE_FloodMessage *incoming_flood)
927 {
928  if (GNUNET_YES != check_proof_of_work(&incoming_flood->origin.public_key,
929  incoming_flood->proof_of_work))
930  {
932  "Proof of work invalid: %llu!\n",
933  (unsigned long long)GNUNET_ntohll(
934  incoming_flood->proof_of_work));
935  GNUNET_break_op(0);
936  return GNUNET_NO;
937  }
938  if ((nse_work_required > 0) &&
939  (GNUNET_OK !=
941  &incoming_flood->purpose,
942  &incoming_flood->signature,
943  &incoming_flood->origin.public_key)))
944  {
945  GNUNET_break_op(0);
946  return GNUNET_NO;
947  }
948  return GNUNET_YES;
949 }
950 
951 
961 static int
963  const struct GNUNET_PeerIdentity *key,
964  void *value)
965 {
966  struct NSEPeerEntry *exclude = cls;
967  struct NSEPeerEntry *peer_entry = value;
968  struct GNUNET_TIME_Relative delay;
969 
970  (void)key;
971  if (peer_entry == exclude)
972  return GNUNET_OK; /* trigger of the update */
973  if (GNUNET_NO == peer_entry->previous_round)
974  {
975  /* still stuck in previous round, no point to update, check that
976  * we are active here though... */
977  if (NULL == peer_entry->transmit_task)
978  {
979  GNUNET_break(0);
980  }
981  return GNUNET_OK;
982  }
983  if (NULL != peer_entry->transmit_task)
984  {
986  peer_entry->transmit_task = NULL;
987  }
988  delay = get_transmit_delay(0);
989  peer_entry->transmit_task =
990  GNUNET_SCHEDULER_add_delayed(delay, &transmit_task_cb, peer_entry);
991  return GNUNET_OK;
992 }
993 
994 
1001 static void
1003  const struct GNUNET_NSE_FloodMessage *incoming_flood)
1004 {
1005  struct NSEPeerEntry *peer_entry = cls;
1006  struct GNUNET_TIME_Absolute ts;
1007  uint32_t matching_bits;
1008  unsigned int idx;
1009 
1010 #if ENABLE_NSE_HISTOGRAM
1011  {
1012  uint64_t t;
1013 
1015  if (NULL != lh)
1016  GNUNET_TESTBED_LOGGER_write(lh, &t, sizeof(uint64_t));
1017  if (NULL != histogram)
1018  GNUNET_BIO_write_int64(histogram, t);
1019  }
1020 #endif
1021  GNUNET_STATISTICS_update(stats, "# flood messages received", 1, GNUNET_NO);
1022  matching_bits = ntohl(incoming_flood->matching_bits);
1023 #if DEBUG_NSE
1024  {
1025  char origin[5];
1026  char pred[5];
1027  struct GNUNET_PeerIdentity os;
1028 
1029  GNUNET_snprintf(origin,
1030  sizeof(origin),
1031  "%s",
1032  GNUNET_i2s(&incoming_flood->origin));
1033  GNUNET_snprintf(pred, sizeof(pred), "%s", GNUNET_i2s(peer_entry->id));
1035  "Flood at %s from `%s' via `%s' at `%s' with bits %u\n",
1037  GNUNET_TIME_absolute_ntoh(incoming_flood->timestamp)),
1038  origin,
1039  pred,
1041  (unsigned int)matching_bits);
1042  }
1043 #endif
1044 
1045 #if ENABLE_NSE_HISTOGRAM
1046  peer_entry->received_messages++;
1047  if (peer_entry->transmitted_messages > 0 &&
1048  peer_entry->last_transmitted_size >= matching_bits)
1049  GNUNET_STATISTICS_update(stats, "# cross messages", 1, GNUNET_NO);
1050 #endif
1051 
1052  ts = GNUNET_TIME_absolute_ntoh(incoming_flood->timestamp);
1054  idx = estimate_index;
1055  else if (ts.abs_value_us ==
1057  idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
1058  else if (ts.abs_value_us == next_timestamp.abs_value_us)
1059  {
1060  if (matching_bits <= ntohl(next_message.matching_bits))
1061  return; /* ignore, simply too early/late */
1062  if (GNUNET_YES != verify_message_crypto(incoming_flood))
1063  {
1065  "Peer %s is likely ill-configured!\n",
1066  GNUNET_i2s(peer_entry->id));
1067  GNUNET_break_op(0);
1068  return;
1069  }
1070  next_message = *incoming_flood;
1071  return;
1072  }
1073  else
1074  {
1076  "# flood messages discarded (clock skew too large)",
1077  1,
1078  GNUNET_NO);
1079  return;
1080  }
1081  if (0 == (GNUNET_memcmp(peer_entry->id, &my_identity)))
1082  {
1083  /* send to self, update our own estimate IF this also comes from us! */
1084  if (0 == GNUNET_memcmp(&incoming_flood->origin, &my_identity))
1086  return;
1087  }
1088  if (matching_bits == ntohl(size_estimate_messages[idx].matching_bits))
1089  {
1090  /* Cancel transmission in the other direction, as this peer clearly has
1091  up-to-date information already. Even if we didn't talk to this peer in
1092  the previous round, we should no longer send it stale information as it
1093  told us about the current round! */
1094  peer_entry->previous_round = GNUNET_YES;
1095  if (idx != estimate_index)
1096  {
1097  /* do not transmit information for the previous round to this peer
1098  anymore (but allow current round) */
1099  return;
1100  }
1101  /* got up-to-date information for current round, cancel transmission to
1102  * this peer altogether */
1103  if (NULL != peer_entry->transmit_task)
1104  {
1106  peer_entry->transmit_task = NULL;
1107  }
1108  return;
1109  }
1110  if (matching_bits < ntohl(size_estimate_messages[idx].matching_bits))
1111  {
1112  if ((idx < estimate_index) && (peer_entry->previous_round == GNUNET_YES))
1113  {
1114  peer_entry->previous_round = GNUNET_NO;
1115  }
1116  /* push back our result now, that peer is spreading bad information... */
1117  if (NULL != peer_entry->transmit_task)
1119  peer_entry->transmit_task =
1121  /* Not closer than our most recent message, no need to do work here */
1123  "# flood messages ignored (had closer already)",
1124  1,
1125  GNUNET_NO);
1126  return;
1127  }
1128  if (GNUNET_YES != verify_message_crypto(incoming_flood))
1129  {
1130  GNUNET_break_op(0);
1131  return;
1132  }
1133  GNUNET_assert(matching_bits >
1134  ntohl(size_estimate_messages[idx].matching_bits));
1135  /* Cancel transmission in the other direction, as this peer clearly has
1136  * up-to-date information already.
1137  */
1138  peer_entry->previous_round = GNUNET_YES;
1139  if (idx == estimate_index)
1140  {
1141  /* cancel any activity for current round */
1142  if (NULL != peer_entry->transmit_task)
1143  {
1145  peer_entry->transmit_task = NULL;
1146  }
1147  }
1148  size_estimate_messages[idx] = *incoming_flood;
1150  htonl(ntohl(incoming_flood->hop_count) + 1);
1151  hop_count_max =
1152  GNUNET_MAX(ntohl(incoming_flood->hop_count) + 1, hop_count_max);
1153  GNUNET_STATISTICS_set(stats,
1154  "# estimated network diameter",
1155  hop_count_max,
1156  GNUNET_NO);
1157 
1158  /* have a new, better size estimate, inform clients */
1160 
1161  /* flood to rest */
1164  peer_entry);
1165 }
1166 
1167 
1175 static void *
1177  const struct GNUNET_PeerIdentity *peer,
1178  struct GNUNET_MQ_Handle *mq)
1179 {
1180  struct NSEPeerEntry *peer_entry;
1181 
1182  (void)cls;
1184  "Peer `%s' connected to us\n",
1185  GNUNET_i2s(peer));
1186  /* set our default transmission options */
1188  /* create our peer entry for this peer */
1189  peer_entry = GNUNET_new(struct NSEPeerEntry);
1190  peer_entry->id = peer;
1191  peer_entry->mq = mq;
1194  peers,
1195  peer_entry->id,
1196  peer_entry,
1198  peer_entry->transmit_task =
1201  peer_entry);
1202  GNUNET_STATISTICS_update(stats, "# peers connected", 1, GNUNET_NO);
1203  return peer_entry;
1204 }
1205 
1206 
1215 static void
1217  const struct GNUNET_PeerIdentity *peer,
1218  void *internal_cls)
1219 {
1220  struct NSEPeerEntry *pos = internal_cls;
1221 
1222  (void)cls;
1224  "Peer `%s' disconnected from us\n",
1225  GNUNET_i2s(peer));
1227  GNUNET_CONTAINER_multipeermap_remove(peers, peer, pos));
1228  if (NULL != pos->transmit_task)
1229  {
1231  pos->transmit_task = NULL;
1232  }
1233  GNUNET_free(pos);
1234  GNUNET_STATISTICS_update(stats, "# peers connected", -1, GNUNET_NO);
1235 }
1236 
1237 
1238 #if ENABLE_NSE_HISTOGRAM
1239 
1246 static void
1247 flush_comp_cb(void *cls, size_t size)
1248 {
1249  (void)cls;
1250  (void)size;
1252  lh = NULL;
1253 }
1254 #endif
1255 
1256 
1262 static void
1263 shutdown_task(void *cls)
1264 {
1265  (void)cls;
1266  if (NULL != flood_task)
1267  {
1268  GNUNET_SCHEDULER_cancel(flood_task);
1269  flood_task = NULL;
1270  }
1271  if (NULL != proof_task)
1272  {
1273  GNUNET_SCHEDULER_cancel(proof_task);
1274  proof_task = NULL;
1275  write_proof(); /* remember progress */
1276  }
1277  if (NULL != nc)
1278  {
1280  nc = NULL;
1281  }
1282  if (NULL != core_api)
1283  {
1284  GNUNET_CORE_disconnect(core_api);
1285  core_api = NULL;
1286  }
1287  if (NULL != stats)
1288  {
1290  stats = NULL;
1291  }
1292  if (NULL != peers)
1293  {
1295  peers = NULL;
1296  }
1297  if (NULL != my_private_key)
1298  {
1299  GNUNET_free(my_private_key);
1300  my_private_key = NULL;
1301  }
1302 #if ENABLE_NSE_HISTOGRAM
1303  if (NULL != logger_test)
1304  {
1305  GNUNET_CLIENT_service_test_cancel(logger_test);
1306  logger_test = NULL;
1307  }
1308  if (NULL != lh)
1309  {
1310  GNUNET_TESTBED_LOGGER_flush(lh, &flush_comp_cb, NULL);
1311  }
1312  if (NULL != histogram)
1313  {
1314  GNUNET_BIO_write_close(histogram);
1315  histogram = NULL;
1316  }
1317 #endif
1318 }
1319 
1320 
1327 static void
1328 core_init(void *cls, const struct GNUNET_PeerIdentity *identity)
1329 {
1330  struct GNUNET_TIME_Absolute now;
1331  struct GNUNET_TIME_Absolute prev_time;
1332 
1333  (void)cls;
1334  if (NULL == identity)
1335  {
1336  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n");
1338  return;
1339  }
1340  GNUNET_assert(0 == GNUNET_memcmp(&my_identity, identity));
1341  now = GNUNET_TIME_absolute_get();
1345  next_timestamp =
1348  estimate_count = 0;
1350  {
1351  int idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
1352  prev_time.abs_value_us =
1354  setup_flood_message(idx, prev_time);
1356  estimate_count++;
1357  }
1358  flood_task =
1360 }
1361 
1362 
1363 #if ENABLE_NSE_HISTOGRAM
1364 
1372 static void
1373 status_cb(void *cls, int status)
1374 {
1375  (void)cls;
1376  logger_test = NULL;
1377  if (GNUNET_YES != status)
1378  {
1379  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Testbed logger not running\n");
1380  return;
1381  }
1382  if (NULL == (lh = GNUNET_TESTBED_LOGGER_connect(cfg)))
1383  {
1385  "Cannot connect to the testbed logger. Exiting.\n");
1387  }
1388 }
1389 #endif
1390 
1391 
1399 static void
1400 run(void *cls,
1401  const struct GNUNET_CONFIGURATION_Handle *c,
1403 {
1404  struct GNUNET_MQ_MessageHandler core_handlers[] =
1405  { GNUNET_MQ_hd_fixed_size(p2p_estimate,
1407  struct GNUNET_NSE_FloodMessage,
1408  NULL),
1410  char *proof;
1412 
1413  (void)cls;
1414  (void)service;
1415  cfg = c;
1417  "NSE",
1418  "INTERVAL",
1420  {
1423  return;
1424  }
1426  "NSE",
1427  "WORKDELAY",
1428  &proof_find_delay))
1429  {
1432  return;
1433  }
1435  "NSE",
1436  "WORKBITS",
1438  {
1441  return;
1442  }
1443  if (nse_work_required >= sizeof(struct GNUNET_HashCode) * 8)
1444  {
1446  "NSE",
1447  "WORKBITS",
1448  _("Value is too large.\n"));
1450  return;
1451  }
1452 
1453 #if ENABLE_NSE_HISTOGRAM
1454  {
1455  char *histogram_dir;
1456  char *histogram_fn;
1457 
1459  "NSE",
1460  "HISTOGRAM_DIR",
1461  &histogram_dir))
1462  {
1463  GNUNET_assert(
1464  0 < GNUNET_asprintf(&histogram_fn, "%s/timestamps", histogram_dir));
1465  GNUNET_free(histogram_dir);
1466  histogram = GNUNET_BIO_write_open(histogram_fn);
1467  if (NULL == histogram)
1469  "Unable to open histogram file `%s'\n",
1470  histogram_fn);
1471  GNUNET_free(histogram_fn);
1472  }
1473  logger_test = GNUNET_CLIENT_service_test("testbed-logger",
1474  cfg,
1476  &status_cb,
1477  NULL);
1478  }
1479 #endif
1480 
1483  GNUNET_assert(NULL != pk);
1484  my_private_key = pk;
1486  if (GNUNET_OK !=
1487  GNUNET_CONFIGURATION_get_value_filename(cfg, "NSE", "PROOFFILE", &proof))
1488  {
1490  GNUNET_free(my_private_key);
1491  my_private_key = NULL;
1493  return;
1494  }
1495  if ((GNUNET_YES != GNUNET_DISK_file_test(proof)) ||
1496  (sizeof(my_proof) !=
1497  GNUNET_DISK_fn_read(proof, &my_proof, sizeof(my_proof))))
1498  my_proof = 0;
1499  GNUNET_free(proof);
1500  proof_task =
1502  &find_proof,
1503  NULL);
1504 
1507  /* Connect to core service and register core handlers */
1508  core_api =
1509  GNUNET_CORE_connect(cfg, /* Main configuration */
1510  NULL, /* Closure passed to functions */
1511  &core_init, /* Call core_init once connected */
1512  &handle_core_connect, /* Handle connects */
1513  &handle_core_disconnect, /* Handle disconnects */
1514  core_handlers); /* Register these handlers */
1515  if (NULL == core_api)
1516  {
1518  return;
1519  }
1520  stats = GNUNET_STATISTICS_create("nse", cfg);
1521 }
1522 
1523 
1532 static void *
1534  struct GNUNET_SERVICE_Client *c,
1535  struct GNUNET_MQ_Handle *mq)
1536 {
1537  (void)cls;
1538  (void)mq;
1539  return c;
1540 }
1541 
1542 
1550 static void
1552  struct GNUNET_SERVICE_Client *c,
1553  void *internal_cls)
1554 {
1555  (void)cls;
1556  GNUNET_assert(c == internal_cls);
1557 }
1558 
1559 
1563 GNUNET_SERVICE_MAIN("nse",
1565  &run,
1568  NULL,
1571  struct GNUNET_MessageHeader,
1572  NULL),
1574 
1575 
1576 #if defined(LINUX) && defined(__GLIBC__)
1577 #include <malloc.h>
1578 
1582 void __attribute__ ((constructor)) GNUNET_ARM_memory_init()
1583 {
1584  mallopt(M_TRIM_THRESHOLD, 4 * 1024);
1585  mallopt(M_TOP_PAD, 1 * 1024);
1586  malloc_trim(0);
1587 }
1588 #endif
1589 
1590 
1591 /* end of gnunet-service-nse.c */
#define GNUNET_MESSAGE_TYPE_NSE_START
client->service message indicating start
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:541
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_copy(const struct GNUNET_MessageHeader *hdr)
Create a new envelope by copying an existing message.
Definition: mq.c:651
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:74
static struct GNUNET_CRYPTO_EddsaPrivateKey * pk
Private key of this peer.
int previous_round
Did we receive or send a message about the previous round to this peer yet? GNUNET_YES if the previou...
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:671
static void shutdown_task(void *cls)
Task run during shutdown.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
uint64_t rel_value_us
The actual value.
static struct GNUNET_TIME_Relative get_transmit_delay(int round_offset)
Get the transmission delay that should be applied for a particular round.
static char * pkey
Public key of the zone to look in, in ASCII.
static int update_flood_times(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Update transmissions for the given peer for the current round based on updated proximity information...
const struct GNUNET_PeerIdentity * id
What is the identity of the peer?
static struct GNUNET_TIME_Relative proof_find_delay
Interval between proof find runs.
Context for the core service connection.
Definition: core_api.c:76
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
static void handle_core_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls)
Method called whenever a peer disconnects.
Handle to a service.
Definition: service.c:114
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1169
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2424
struct GNUNET_TIME_AbsoluteNBO timestamp
Timestamp at which the server received the message.
Definition: nse.h:56
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
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:1284
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static struct GNUNET_CONTAINER_MultiPeerMap * peers
Map of all connected peers.
unsigned int GNUNET_CRYPTO_hash_matching_bits(const struct GNUNET_HashCode *first, const struct GNUNET_HashCode *second)
Determine how many low order bits match in two struct GNUNET_HashCodes.
Definition: crypto_hash.c:256
static struct GNUNET_SCHEDULER_Task * proof_task
Task scheduled to compute our proof.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD
P2P message sent from nearest peer.
int GNUNET_BIO_write_int64(struct GNUNET_BIO_WriteHandle *h, int64_t i)
Write an (u)int64_t.
Definition: bio.c:597
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TESTBED_LOGGER_Handle * GNUNET_TESTBED_LOGGER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the testbed logger service.
static struct GNUNET_SCHEDULER_Task * flood_task
Task scheduled to update our flood message for the next round.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_NSE_ESTIMATE.
Definition: nse.h:46
uint32_t matching_bits
Number of matching bits between the hash of timestamp and the initiator&#39;s public key.
static struct GNUNET_NSE_FloodMessage next_message
Message for the next round, if we got any.
int GNUNET_CRYPTO_eddsa_sign(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:989
Network size estimate sent from the service to clients.
Definition: nse.h:42
#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)
static int schedule_current_round(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Schedule transmission for the given peer for the current round based on what we know about the desire...
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define HISTORY_SIZE
Over how many values do we calculate the weighted average?
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:393
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
static struct GNUNET_SCHEDULER_Task * t
Main task.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static struct GNUNET_PeerIdentity my_identity
The peer identity of this peer.
#define GNUNET_MESSAGE_TYPE_NSE_ESTIMATE
service->client message indicating
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.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
static struct GNUNET_TIME_Relative gnunet_nse_interval
Interval for sending network size estimation flood requests.
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Handle network size estimate clients.
static unsigned long long nse_work_required
Amount of work required (W-bit collisions) for NSE proofs, in collision-bits.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:158
uint64_t abs_value_us
The actual value.
ssize_t GNUNET_DISK_fn_write(const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file.
Definition: disk.c:877
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
static void transmit_task_cb(void *cls)
Task that triggers a NSE P2P transmission.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
GNUNET_SERVICE_MAIN("nse", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(start, GNUNET_MESSAGE_TYPE_NSE_START, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Handle to a client that is connected to a service.
Definition: service.c:246
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
static void write_proof()
Write our current proof to disk.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
static struct GNUNET_TIME_Relative get_delay_randomization(uint32_t matching_bits)
What delay randomization should we apply for a given number of matching bits?
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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:1237
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1191
static uint32_t hop_count_max
Current hop counter estimate (estimate for network diameter).
int GNUNET_CRYPTO_eddsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:1116
struct GNUNET_CRYPTO_EddsaSignature signature
Signature (over range specified in purpose).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
static uint64_t proof
Definition: gnunet-scrypt.c:41
Network size estimate reply; sent when "this" peer&#39;s timer has run out before receiving a valid reply...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
double std_deviation
The standard deviation (rounded down to the nearest integer) of size estimations. ...
Definition: nse.h:68
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
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:1264
static uint32_t get_matching_bits(struct GNUNET_TIME_Absolute timestamp, const struct GNUNET_PeerIdentity *id)
Get the number of matching bits that the given timestamp has to the given peer ID.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:686
static void find_proof(void *cls)
Find our proof of work.
static unsigned int estimate_index
Index of most recent estimate.
static double current_size_estimate
The current network size estimate.
uint16_t status
See PRISM_STATUS_*-constants.
static struct GNUNET_NotificationContext * nc
Notification context, simplifies client broadcasts.
static char buf[2048]
static int result
Global testing status.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static struct GNUNET_NSE_FloodMessage size_estimate_messages[64]
Array of recent size estimate messages.
Handle for buffered writing.
Definition: bio.c:378
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
Internal representation of the hash map.
struct GNUNET_PeerIdentity origin
Public key of the originator.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
A 512-bit hashcode.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose.
Message handler for a specific message type.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static void pow_hash(const void *buf, size_t buf_len, struct GNUNET_HashCode *result)
Calculate the &#39;proof-of-work&#39; hash (an expensive hash).
static double get_matching_bits_delay(uint32_t matching_bits)
How long should we delay a message to go the given number of matching bits?
#define NSE_PRIORITY
Message priority to use.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
Run when otherwise idle.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static void handle_p2p_estimate(void *cls, const struct GNUNET_NSE_FloodMessage *incoming_flood)
Core handler for size estimate flooding messages.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned int size
Size of the "table".
Definition: peer.c:66
uint64_t proof_of_work
Proof of work, causing leading zeros when hashed with pkey.
int GNUNET_CRYPTO_hash_get_bit(const struct GNUNET_HashCode *code, unsigned int bit)
Obtain a bit from a hashcode.
Definition: crypto_hash.c:236
struct GNUNET_CORE_Handle * GNUNET_CORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, GNUNET_CORE_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Connect to the core service.
Definition: core_api.c:690
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:728
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static double current_std_dev
The standard deviation of the last HISTORY_SIZE network size estimates.
static void setup_estimate_message(struct GNUNET_NSE_ClientMessage *em)
Initialize a message to clients with the current network size estimate.
static unsigned int count_leading_zeroes(const struct GNUNET_HashCode *hash)
Count the leading zeroes in hash.
struct GNUNET_SCHEDULER_Task * transmit_task
Task scheduled to send message to this peer.
static void update_network_size_estimate()
We&#39;ve sent on our flood message or one that we received which was validated and closer than ours...
double size_estimate
The current estimated network size.
Definition: nse.h:61
#define ROUND_SIZE
int GNUNET_BIO_write_close(struct GNUNET_BIO_WriteHandle *h)
Close an open file for writing.
Definition: bio.c:436
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
an ECC signature using EdDSA.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:272
static struct GNUNET_CORE_Handle * core_api
Handle to the core service.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:119
static void * handle_core_connect(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a peer connects.
Handle to a message queue.
Definition: mq.c:84
struct GNUNET_TIME_AbsoluteNBO timestamp
The current timestamp value (which all peers should agree on).
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
Private ECC key encoded for transmission.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_MQ_set_options(struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_PriorityPreferences pp)
Set application-specific options for this queue.
Definition: mq.c:1063
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition: nc.c:187
enum RadiotapType __attribute__
The identity of the host (wraps the signing key of the peer).
Connection handle for the logger service.
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
The private key of this peer.
struct GNUNET_MQ_Handle * mq
Core handle for sending messages to this peer.
#define GNUNET_PACKED
gcc-ism to get packed structs.
static unsigned int estimate_count
Number of valid entries in the history.
configuration data
Definition: configuration.c:83
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:408
static struct GNUNET_TIME_Absolute next_timestamp
The next major time.
static int check_proof_of_work(const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, uint64_t val)
Check whether the given public key and integer are a valid proof of work.
static uint64_t my_proof
Proof of work for this peer.
static struct GNUNET_TIME_Absolute current_timestamp
The current major time.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
uint32_t hop_count
Number of hops this message has taken so far.
#define GNUNET_SIGNATURE_PURPOSE_NSE_SEND
Signature of a network size estimate message.
Common type definitions for the network size estimation service and API.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GNUNET_TESTBED_LOGGER_write(struct GNUNET_TESTBED_LOGGER_Handle *h, const void *data, size_t size)
Send data to be logged to the logger service.
static void handle_start(void *cls, const struct GNUNET_MessageHeader *message)
Handler for START message from client, triggers an immediate current network estimate notification...
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer&#39;s key from the file specified in the configuration...
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
static void core_init(void *cls, const struct GNUNET_PeerIdentity *identity)
Called on core init/fail.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:135
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:351
void GNUNET_TESTBED_LOGGER_flush(struct GNUNET_TESTBED_LOGGER_Handle *h, GNUNET_TESTBED_LOGGER_FlushCompletion cb, void *cb_cls)
Flush the buffered data to the logger service.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:741
static unsigned long long matching_bits
Number of matching bits required for revocation.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1214
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:655
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
void GNUNET_TESTBED_LOGGER_disconnect(struct GNUNET_TESTBED_LOGGER_Handle *h)
Disconnect from the logger service.
static int verify_message_crypto(const struct GNUNET_NSE_FloodMessage *incoming_flood)
An incoming flood message has been received which claims to have more bits matching than any we know ...
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static void update_flood_message(void *cls)
Update our flood message to be sent (and our timestamps).
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
double GNUNET_hton_double(double d)
Convert double to network byte order.
Definition: common_endian.c:66
static void setup_flood_message(unsigned int slot, struct GNUNET_TIME_Absolute ts)
Setup a flood message in our history array at the given slot offset for the given timestamp...
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:791
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
uint32_t reserved
For alignment.
Definition: nse.h:51
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static GNUNET_NETWORK_STRUCT_END const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
Per-peer information.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...