GNUnet  0.11.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 #ifdef BSD
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 
119 static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
120 
121 
126 {
131 
135  const struct GNUNET_PeerIdentity *id;
136 
141 
148 
149 #if ENABLE_NSE_HISTOGRAM
150 
153  unsigned int received_messages;
154 
158  unsigned int transmitted_messages;
159 
163  unsigned int last_transmitted_size;
164 #endif
165 };
166 
167 
169 
176 {
180  struct GNUNET_MessageHeader header;
181 
185  uint32_t hop_count GNUNET_PACKED;
186 
191 
196  struct GNUNET_TIME_AbsoluteNBO timestamp;
197 
204 
208  struct GNUNET_PeerIdentity origin;
209 
214 
219 };
221 
225 static const struct GNUNET_CONFIGURATION_Handle *cfg;
226 
231 
236 
241 
246 static double current_size_estimate;
247 
252 static double current_std_dev = NAN;
253 
257 static uint32_t hop_count_max;
258 
263 
268 
272 static unsigned int estimate_index;
273 
277 static unsigned int estimate_count;
278 
283 
288 
293 
298 
303 
308 
313 
317 static uint64_t my_proof;
318 
319 
326 static void
328 {
329  double mean;
330  double sum;
331  double std_dev;
332  double variance;
333  double val;
334  double nsize;
335 
336 #define WEST 1
337  /* Weighted incremental algorithm for stddev according to West (1979) */
338 #if WEST
339  double sumweight;
340  double weight;
341  double q;
342  double r;
343  double temp;
344 
345  mean = 0.0;
346  sum = 0.0;
347  sumweight = 0.0;
348  variance = 0.0;
349  for (unsigned int i = 0; i < estimate_count; i++)
350  {
351  unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE;
352 
353  val = htonl (size_estimate_messages[j].matching_bits);
354  weight = estimate_count + 1 - i;
355 
356  temp = weight + sumweight;
357  q = val - mean;
358  r = q * weight / temp;
359  mean += r;
360  sum += sumweight * q * r;
361  sumweight = temp;
362  }
363  if (estimate_count > 0)
364  variance = (sum / sumweight) * estimate_count / (estimate_count - 1.0);
365 #else
366  /* trivial version for debugging */
367  double vsq;
368 
369  /* non-weighted trivial version */
370  sum = 0.0;
371  vsq = 0.0;
372  variance = 0.0;
373  mean = 0.0;
374 
375  for (unsigned int i = 0; i < estimate_count; i++)
376  {
377  unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE;
378 
379  val = htonl (size_estimate_messages[j].matching_bits);
380  sum += val;
381  vsq += val * val;
382  }
383  if (0 != estimate_count)
384  {
385  mean = sum / estimate_count;
386  variance = (vsq - mean * sum)
387  / (estimate_count - 1.0); // terrible for numerical stability...
388  }
389 #endif
390  if (variance >= 0)
391  std_dev = sqrt (variance);
392  else
393  std_dev = variance; /* must be infinity due to estimate_count == 0 */
394  current_std_dev = std_dev;
395  current_size_estimate = mean;
396 
397  em->header.size = htons (sizeof(struct GNUNET_NSE_ClientMessage));
399  em->reserved = htonl (0);
401  {
402  double se = mean - 0.332747;
403  unsigned int j = GNUNET_CONTAINER_multipeermap_size (peers);
404  if (0 == j)
405  j = 1; /* Avoid log2(0); can only happen if CORE didn't report
406  connection to self yet */
407  nsize = log2 (j);
408  em->size_estimate = GNUNET_hton_double (GNUNET_MAX (se, nsize));
409  em->std_deviation = GNUNET_hton_double (std_dev);
410  GNUNET_STATISTICS_set (stats,
411  "# nodes in the network (estimate)",
412  (uint64_t) pow (2, GNUNET_MAX (se, nsize)),
413  GNUNET_NO);
414  }
415 }
416 
417 
427 static void
428 handle_start (void *cls, const struct GNUNET_MessageHeader *message)
429 {
430  struct GNUNET_SERVICE_Client *client = cls;
431  struct GNUNET_MQ_Handle *mq;
432  struct GNUNET_NSE_ClientMessage em;
433  struct GNUNET_MQ_Envelope *env;
434 
435  (void) message;
436  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received START message from client\n");
437  mq = GNUNET_SERVICE_client_get_mq (client);
440  env = GNUNET_MQ_msg_copy (&em.header);
441  GNUNET_MQ_send (mq, env);
443 }
444 
445 
452 static double
454 {
455  /* Calculated as: S + f/2 - (f / pi) * (atan(x - p')) */
456  // S is next_timestamp (ignored in return value)
457  // f is frequency (gnunet_nse_interval)
458  // x is matching_bits
459  // p' is current_size_estimate
460  return ((double) gnunet_nse_interval.rel_value_us / (double) 2.0)
462  * atan (matching_bits - current_size_estimate));
463 }
464 
465 
472 static struct GNUNET_TIME_Relative
474 {
475 #if USE_RANDOM_DELAYS
476  struct GNUNET_TIME_Relative ret;
477  uint32_t i;
478  double d;
479 
481  i = (uint32_t) (d / (double) (hop_count_max + 1));
482  ret.rel_value_us = i;
484  "Randomizing flood using latencies up to %s\n",
486  ret.rel_value_us =
488  return ret;
489 #else
490  return GNUNET_TIME_UNIT_ZERO;
491 #endif
492 }
493 
494 
502 static uint32_t
504  const struct GNUNET_PeerIdentity *id)
505 {
506  struct GNUNET_HashCode timestamp_hash;
507  struct GNUNET_HashCode pid_hash;
508 
509  GNUNET_CRYPTO_hash (&timestamp.abs_value_us,
510  sizeof(timestamp.abs_value_us),
511  &timestamp_hash);
512  GNUNET_CRYPTO_hash (id, sizeof(struct GNUNET_PeerIdentity), &pid_hash);
513  return GNUNET_CRYPTO_hash_matching_bits (&timestamp_hash, &pid_hash);
514 }
515 
516 
525 static struct GNUNET_TIME_Relative
526 get_transmit_delay (int round_offset)
527 {
528  struct GNUNET_TIME_Relative ret;
529  struct GNUNET_TIME_Absolute tgt;
530  double dist_delay;
531  uint32_t matching_bits;
532 
533  switch (round_offset)
534  {
535  case -1:
536  /* previous round is randomized between 0 and 50 ms */
537 #if USE_RANDOM_DELAYS
538  ret.rel_value_us =
540 #else
541  ret = GNUNET_TIME_UNIT_ZERO;
542 #endif
544  "Transmitting previous round behind schedule in %s\n",
546  return ret;
547 
548  case 0:
549  /* current round is based on best-known matching_bits */
550  matching_bits =
551  ntohl (size_estimate_messages[estimate_index].matching_bits);
552  dist_delay = get_matching_bits_delay (matching_bits);
553  dist_delay += get_delay_randomization (matching_bits).rel_value_us;
554  ret.rel_value_us = (uint64_t) dist_delay;
556  "For round %s, delay for %u matching bits is %s\n",
558  (unsigned int) matching_bits,
560  /* now consider round start time and add delay to it */
563  }
564  GNUNET_break (0);
566 }
567 
568 
574 static void
575 transmit_task_cb (void *cls)
576 {
577  struct NSEPeerEntry *peer_entry = cls;
578  unsigned int idx;
579  struct GNUNET_MQ_Envelope *env;
580 
581  peer_entry->transmit_task = NULL;
582  idx = estimate_index;
583  if (GNUNET_NO == peer_entry->previous_round)
584  {
585  idx = (idx + HISTORY_SIZE - 1) % HISTORY_SIZE;
586  peer_entry->previous_round = GNUNET_YES;
587  peer_entry->transmit_task =
590  peer_entry);
591  }
592  if ((0 == ntohl (size_estimate_messages[idx].hop_count)) &&
593  (NULL != proof_task))
594  {
596  "# flood messages not generated (no proof yet)",
597  1,
598  GNUNET_NO);
599  return;
600  }
601  if (0 == ntohs (size_estimate_messages[idx].header.size))
602  {
604  "# flood messages not generated (lack of history)",
605  1,
606  GNUNET_NO);
607  return;
608  }
610  "In round %s, sending to `%s' estimate with %u bits\n",
613  size_estimate_messages[idx].timestamp)),
614  GNUNET_i2s (peer_entry->id),
615  (unsigned int) ntohl (size_estimate_messages[idx].matching_bits));
616  if (0 == ntohl (size_estimate_messages[idx].hop_count))
617  GNUNET_STATISTICS_update (stats, "# flood messages started", 1, GNUNET_NO);
619  "# flood messages transmitted",
620  1,
621  GNUNET_NO);
622 #if ENABLE_NSE_HISTOGRAM
623  peer_entry->transmitted_messages++;
624  peer_entry->last_transmitted_size =
625  ntohl (size_estimate_messages[idx].matching_bits);
626 #endif
627  env = GNUNET_MQ_msg_copy (&size_estimate_messages[idx].header);
628  GNUNET_MQ_send (peer_entry->mq, env);
629 }
630 
631 
638 static void
640 {
641  struct GNUNET_NSE_ClientMessage em;
642 
645 }
646 
647 
655 static void
656 setup_flood_message (unsigned int slot, struct GNUNET_TIME_Absolute ts)
657 {
658  struct GNUNET_NSE_FloodMessage *fm;
659  uint32_t matching_bits;
660 
661  matching_bits = get_matching_bits (ts, &my_identity);
662  fm = &size_estimate_messages[slot];
663  fm->header.size = htons (sizeof(struct GNUNET_NSE_FloodMessage));
665  fm->hop_count = htonl (0);
667  fm->purpose.size =
668  htonl (sizeof(struct GNUNET_NSE_FloodMessage)
669  - sizeof(struct GNUNET_MessageHeader) - sizeof(uint32_t)
670  - sizeof(struct GNUNET_CRYPTO_EddsaSignature));
671  fm->matching_bits = htonl (matching_bits);
673  fm->origin = my_identity;
674  fm->proof_of_work = my_proof;
675  if (nse_work_required > 0)
677  GNUNET_CRYPTO_eddsa_sign_ (my_private_key,
678  &fm->purpose,
679  &fm->signature));
680  else
681  memset (&fm->signature, 0, sizeof(fm->signature));
682 }
683 
684 
694 static int
696  const struct GNUNET_PeerIdentity *key,
697  void *value)
698 {
699  struct NSEPeerEntry *peer_entry = value;
700  struct GNUNET_TIME_Relative delay;
701 
702  (void) cls;
703  (void) key;
704  if (NULL != peer_entry->transmit_task)
705  {
707  peer_entry->previous_round = GNUNET_NO;
708  }
709 #if ENABLE_NSE_HISTOGRAM
710  if (peer_entry->received_messages > 1)
712  "# extra messages",
713  peer_entry->received_messages - 1,
714  GNUNET_NO);
715  peer_entry->transmitted_messages = 0;
716  peer_entry->last_transmitted_size = 0;
717  peer_entry->received_messages = 0;
718 #endif
719  delay =
720  get_transmit_delay ((GNUNET_NO == peer_entry->previous_round) ? -1 : 0);
721  peer_entry->transmit_task =
722  GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry);
723  return GNUNET_OK;
724 }
725 
726 
732 static void
734 {
735  struct GNUNET_TIME_Relative offset;
736 
737  (void) cls;
738  flood_task = NULL;
740  if (0 != offset.rel_value_us)
741  {
742  /* somehow run early, delay more */
743  flood_task =
745  return;
746  }
749  estimate_count++;
756  ntohl (next_message.matching_bits)))
757  {
758  /* we received a message for this round way early, use it! */
761  htonl (1 + ntohl (next_message.hop_count));
762  }
763  else
765  next_message.matching_bits = htonl (0); /* reset for 'next' round */
766  hop_count_max = 0;
767  for (unsigned int i = 0; i < HISTORY_SIZE; i++)
768  hop_count_max =
769  GNUNET_MAX (ntohl (size_estimate_messages[i].hop_count), hop_count_max);
771  flood_task =
773 }
774 
775 
782 static unsigned int
784 {
785  unsigned int hash_count;
786 
787  hash_count = 0;
788  while (0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count))
789  hash_count++;
790  return hash_count;
791 }
792 
793 
802 static int
804  uint64_t val)
805 {
806  char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
807  + sizeof(val)] GNUNET_ALIGN;
808  struct GNUNET_HashCode result;
809 
810  GNUNET_memcpy (buf, &val, sizeof(val));
811  GNUNET_memcpy (&buf[sizeof(val)],
812  pkey,
813  sizeof(struct GNUNET_CRYPTO_EddsaPublicKey));
814  GNUNET_CRYPTO_pow_hash (&salt,
815  buf,
816  sizeof(buf),
817  &result);
818  return (count_leading_zeroes (&result) >= nse_work_required) ? GNUNET_YES
819  : GNUNET_NO;
820 }
821 
822 
826 static void
828 {
829  char *proof;
830 
831  if (GNUNET_OK !=
832  GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &proof))
833  return;
834  if (sizeof(my_proof) != GNUNET_DISK_fn_write (proof,
835  &my_proof,
836  sizeof(my_proof),
840  GNUNET_free (proof);
841 }
842 
843 
849 static void
850 find_proof (void *cls)
851 {
852 #define ROUND_SIZE 10
853  uint64_t counter;
854  char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
855  + sizeof(uint64_t)] GNUNET_ALIGN;
856  struct GNUNET_HashCode result;
857  unsigned int i;
858 
859  (void) cls;
860  proof_task = NULL;
861  GNUNET_memcpy (&buf[sizeof(uint64_t)],
862  &my_identity,
863  sizeof(struct GNUNET_PeerIdentity));
864  i = 0;
865  counter = my_proof;
866  while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
867  {
868  GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
869  GNUNET_CRYPTO_pow_hash (&salt,
870  buf,
871  sizeof(buf),
872  &result);
873  if (nse_work_required <= count_leading_zeroes (&result))
874  {
875  my_proof = counter;
877  "Proof of work found: %llu!\n",
878  (unsigned long long) GNUNET_ntohll (counter));
879  write_proof ();
881  return;
882  }
883  counter++;
884  i++;
885  }
886  if (my_proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE))
887  {
889  "Testing proofs currently at %llu\n",
890  (unsigned long long) counter);
891  /* remember progress every 100 rounds */
892  my_proof = counter;
893  write_proof ();
894  }
895  else
896  {
897  my_proof = counter;
898  }
899  proof_task =
902  &find_proof,
903  NULL);
904 }
905 
906 
916 static int
917 verify_message_crypto (const struct GNUNET_NSE_FloodMessage *incoming_flood)
918 {
919  if (GNUNET_YES != check_proof_of_work (&incoming_flood->origin.public_key,
920  incoming_flood->proof_of_work))
921  {
923  "Proof of work invalid: %llu!\n",
924  (unsigned long long) GNUNET_ntohll (
925  incoming_flood->proof_of_work));
926  GNUNET_break_op (0);
927  return GNUNET_NO;
928  }
929  if ((nse_work_required > 0) &&
930  (GNUNET_OK !=
932  &incoming_flood->purpose,
933  &incoming_flood->signature,
934  &incoming_flood->origin.public_key)))
935  {
936  GNUNET_break_op (0);
937  return GNUNET_NO;
938  }
939  return GNUNET_YES;
940 }
941 
942 
952 static int
954  const struct GNUNET_PeerIdentity *key,
955  void *value)
956 {
957  struct NSEPeerEntry *exclude = cls;
958  struct NSEPeerEntry *peer_entry = value;
959  struct GNUNET_TIME_Relative delay;
960 
961  (void) key;
962  if (peer_entry == exclude)
963  return GNUNET_OK; /* trigger of the update */
964  if (GNUNET_NO == peer_entry->previous_round)
965  {
966  /* still stuck in previous round, no point to update, check that
967  * we are active here though... */
968  if (NULL == peer_entry->transmit_task)
969  {
970  GNUNET_break (0);
971  }
972  return GNUNET_OK;
973  }
974  if (NULL != peer_entry->transmit_task)
975  {
977  peer_entry->transmit_task = NULL;
978  }
979  delay = get_transmit_delay (0);
980  peer_entry->transmit_task =
981  GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry);
982  return GNUNET_OK;
983 }
984 
985 
992 static void
994  const struct GNUNET_NSE_FloodMessage *incoming_flood)
995 {
996  struct NSEPeerEntry *peer_entry = cls;
997  struct GNUNET_TIME_Absolute ts;
998  uint32_t matching_bits;
999  unsigned int idx;
1000 
1001 #if ENABLE_NSE_HISTOGRAM
1002  {
1003  uint64_t t;
1004 
1006  if (NULL != lh)
1007  GNUNET_TESTBED_LOGGER_write (lh, &t, sizeof(uint64_t));
1008  if (NULL != histogram)
1009  GNUNET_BIO_write_int64 (histogram, "histogram-time", t);
1010  }
1011 #endif
1012  GNUNET_STATISTICS_update (stats, "# flood messages received", 1, GNUNET_NO);
1013  matching_bits = ntohl (incoming_flood->matching_bits);
1014 #if DEBUG_NSE
1015  {
1016  char origin[5];
1017  char pred[5];
1018  struct GNUNET_PeerIdentity os;
1019 
1020  GNUNET_snprintf (origin,
1021  sizeof(origin),
1022  "%s",
1023  GNUNET_i2s (&incoming_flood->origin));
1024  GNUNET_snprintf (pred, sizeof(pred), "%s", GNUNET_i2s (peer_entry->id));
1026  "Flood at %s from `%s' via `%s' at `%s' with bits %u\n",
1028  GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp)),
1029  origin,
1030  pred,
1032  (unsigned int) matching_bits);
1033  }
1034 #endif
1035 
1036 #if ENABLE_NSE_HISTOGRAM
1037  peer_entry->received_messages++;
1038  if ((peer_entry->transmitted_messages > 0) &&
1039  (peer_entry->last_transmitted_size >= matching_bits) )
1040  GNUNET_STATISTICS_update (stats, "# cross messages", 1, GNUNET_NO);
1041 #endif
1042 
1043  ts = GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp);
1045  idx = estimate_index;
1046  else if (ts.abs_value_us ==
1048  idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
1049  else if (ts.abs_value_us == next_timestamp.abs_value_us)
1050  {
1051  if (matching_bits <= ntohl (next_message.matching_bits))
1052  return; /* ignore, simply too early/late */
1053  if (GNUNET_YES != verify_message_crypto (incoming_flood))
1054  {
1056  "Peer %s is likely ill-configured!\n",
1057  GNUNET_i2s (peer_entry->id));
1058  GNUNET_break_op (0);
1059  return;
1060  }
1061  next_message = *incoming_flood;
1062  return;
1063  }
1064  else
1065  {
1066  GNUNET_STATISTICS_update (stats,
1067  "# flood messages discarded (clock skew too large)",
1068  1,
1069  GNUNET_NO);
1070  return;
1071  }
1072  if (0 == (GNUNET_memcmp (peer_entry->id, &my_identity)))
1073  {
1074  /* send to self, update our own estimate IF this also comes from us! */
1075  if (0 == GNUNET_memcmp (&incoming_flood->origin, &my_identity))
1077  return;
1078  }
1079  if (matching_bits == ntohl (size_estimate_messages[idx].matching_bits))
1080  {
1081  /* Cancel transmission in the other direction, as this peer clearly has
1082  up-to-date information already. Even if we didn't talk to this peer in
1083  the previous round, we should no longer send it stale information as it
1084  told us about the current round! */
1085  peer_entry->previous_round = GNUNET_YES;
1086  if (idx != estimate_index)
1087  {
1088  /* do not transmit information for the previous round to this peer
1089  anymore (but allow current round) */
1090  return;
1091  }
1092  /* got up-to-date information for current round, cancel transmission to
1093  * this peer altogether */
1094  if (NULL != peer_entry->transmit_task)
1095  {
1096  GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
1097  peer_entry->transmit_task = NULL;
1098  }
1099  return;
1100  }
1101  if (matching_bits < ntohl (size_estimate_messages[idx].matching_bits))
1102  {
1103  if ((idx < estimate_index) && (peer_entry->previous_round == GNUNET_YES))
1104  {
1105  peer_entry->previous_round = GNUNET_NO;
1106  }
1107  /* push back our result now, that peer is spreading bad information... */
1108  if (NULL != peer_entry->transmit_task)
1109  GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
1110  peer_entry->transmit_task =
1112  /* Not closer than our most recent message, no need to do work here */
1113  GNUNET_STATISTICS_update (stats,
1114  "# flood messages ignored (had closer already)",
1115  1,
1116  GNUNET_NO);
1117  return;
1118  }
1119  if (GNUNET_YES != verify_message_crypto (incoming_flood))
1120  {
1121  GNUNET_break_op (0);
1122  return;
1123  }
1124  GNUNET_assert (matching_bits >
1125  ntohl (size_estimate_messages[idx].matching_bits));
1126  /* Cancel transmission in the other direction, as this peer clearly has
1127  * up-to-date information already.
1128  */
1129  peer_entry->previous_round = GNUNET_YES;
1130  if (idx == estimate_index)
1131  {
1132  /* cancel any activity for current round */
1133  if (NULL != peer_entry->transmit_task)
1134  {
1135  GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
1136  peer_entry->transmit_task = NULL;
1137  }
1138  }
1139  size_estimate_messages[idx] = *incoming_flood;
1141  htonl (ntohl (incoming_flood->hop_count) + 1);
1142  hop_count_max =
1143  GNUNET_MAX (ntohl (incoming_flood->hop_count) + 1, hop_count_max);
1144  GNUNET_STATISTICS_set (stats,
1145  "# estimated network diameter",
1146  hop_count_max,
1147  GNUNET_NO);
1148 
1149  /* have a new, better size estimate, inform clients */
1151 
1152  /* flood to rest */
1155  peer_entry);
1156 }
1157 
1158 
1166 static void *
1168  const struct GNUNET_PeerIdentity *peer,
1169  struct GNUNET_MQ_Handle *mq)
1170 {
1171  struct NSEPeerEntry *peer_entry;
1172 
1173  (void) cls;
1175  "Peer `%s' connected to us\n",
1176  GNUNET_i2s (peer));
1177  /* set our default transmission options */
1179  /* create our peer entry for this peer */
1180  peer_entry = GNUNET_new (struct NSEPeerEntry);
1181  peer_entry->id = peer;
1182  peer_entry->mq = mq;
1185  peers,
1186  peer_entry->id,
1187  peer_entry,
1189  peer_entry->transmit_task =
1192  peer_entry);
1193  GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO);
1194  return peer_entry;
1195 }
1196 
1197 
1206 static void
1208  const struct GNUNET_PeerIdentity *peer,
1209  void *internal_cls)
1210 {
1211  struct NSEPeerEntry *pos = internal_cls;
1212 
1213  (void) cls;
1215  "Peer `%s' disconnected from us\n",
1216  GNUNET_i2s (peer));
1218  GNUNET_CONTAINER_multipeermap_remove (peers, peer, pos));
1219  if (NULL != pos->transmit_task)
1220  {
1222  pos->transmit_task = NULL;
1223  }
1224  GNUNET_free (pos);
1225  GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO);
1226 }
1227 
1228 
1229 #if ENABLE_NSE_HISTOGRAM
1230 
1237 static void
1238 flush_comp_cb (void *cls, size_t size)
1239 {
1240  (void) cls;
1241  (void) size;
1243  lh = NULL;
1244 }
1245 
1246 
1247 #endif
1248 
1249 
1255 static void
1256 shutdown_task (void *cls)
1257 {
1258  (void) cls;
1259  if (NULL != flood_task)
1260  {
1261  GNUNET_SCHEDULER_cancel (flood_task);
1262  flood_task = NULL;
1263  }
1264  if (NULL != proof_task)
1265  {
1266  GNUNET_SCHEDULER_cancel (proof_task);
1267  proof_task = NULL;
1268  write_proof (); /* remember progress */
1269  }
1270  if (NULL != nc)
1271  {
1273  nc = NULL;
1274  }
1275  if (NULL != core_api)
1276  {
1277  GNUNET_CORE_disconnect (core_api);
1278  core_api = NULL;
1279  }
1280  if (NULL != stats)
1281  {
1283  stats = NULL;
1284  }
1285  if (NULL != peers)
1286  {
1288  peers = NULL;
1289  }
1290  if (NULL != my_private_key)
1291  {
1292  GNUNET_free (my_private_key);
1293  my_private_key = NULL;
1294  }
1295 #if ENABLE_NSE_HISTOGRAM
1296  if (NULL != logger_test)
1297  {
1298  GNUNET_CLIENT_service_test_cancel (logger_test);
1299  logger_test = NULL;
1300  }
1301  if (NULL != lh)
1302  {
1303  GNUNET_TESTBED_LOGGER_flush (lh, &flush_comp_cb, NULL);
1304  }
1305  if (NULL != histogram)
1306  {
1307  GNUNET_BIO_write_close (histogram, NULL);
1308  histogram = NULL;
1309  }
1310 #endif
1311 }
1312 
1313 
1320 static void
1321 core_init (void *cls, const struct GNUNET_PeerIdentity *identity)
1322 {
1323  struct GNUNET_TIME_Absolute now;
1324  struct GNUNET_TIME_Absolute prev_time;
1325 
1326  (void) cls;
1327  if (NULL == identity)
1328  {
1329  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n");
1331  return;
1332  }
1333  GNUNET_assert (0 == GNUNET_memcmp (&my_identity, identity));
1334  now = GNUNET_TIME_absolute_get ();
1338  next_timestamp =
1341  estimate_count = 0;
1343  {
1344  int idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
1345  prev_time.abs_value_us =
1347  setup_flood_message (idx, prev_time);
1349  estimate_count++;
1350  }
1351  flood_task =
1353 }
1354 
1355 
1356 #if ENABLE_NSE_HISTOGRAM
1357 
1365 static void
1366 status_cb (void *cls, int status)
1367 {
1368  (void) cls;
1369  logger_test = NULL;
1370  if (GNUNET_YES != status)
1371  {
1372  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed logger not running\n");
1373  return;
1374  }
1375  if (NULL == (lh = GNUNET_TESTBED_LOGGER_connect (cfg)))
1376  {
1378  "Cannot connect to the testbed logger. Exiting.\n");
1380  }
1381 }
1382 
1383 
1384 #endif
1385 
1386 
1394 static void
1395 run (void *cls,
1396  const struct GNUNET_CONFIGURATION_Handle *c,
1398 {
1399  struct GNUNET_MQ_MessageHandler core_handlers[] =
1400  { GNUNET_MQ_hd_fixed_size (p2p_estimate,
1402  struct GNUNET_NSE_FloodMessage,
1403  NULL),
1404  GNUNET_MQ_handler_end () };
1405  char *proof;
1407 
1408  (void) cls;
1409  (void) service;
1410  cfg = c;
1412  "NSE",
1413  "INTERVAL",
1415  {
1418  return;
1419  }
1421  "NSE",
1422  "WORKDELAY",
1423  &proof_find_delay))
1424  {
1425  GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKDELAY");
1427  return;
1428  }
1430  "NSE",
1431  "WORKBITS",
1433  {
1436  return;
1437  }
1438  if (nse_work_required >= sizeof(struct GNUNET_HashCode) * 8)
1439  {
1441  "NSE",
1442  "WORKBITS",
1443  _ ("Value is too large.\n"));
1445  return;
1446  }
1447 
1448 #if ENABLE_NSE_HISTOGRAM
1449  {
1450  char *histogram_dir;
1451  char *histogram_fn;
1452 
1454  "NSE",
1455  "HISTOGRAM_DIR",
1456  &histogram_dir))
1457  {
1458  GNUNET_assert (
1459  0 < GNUNET_asprintf (&histogram_fn, "%s/timestamps", histogram_dir));
1460  GNUNET_free (histogram_dir);
1461  histogram = GNUNET_BIO_write_open_file (histogram_fn);
1462  if (NULL == histogram)
1464  "Unable to open histogram file `%s'\n",
1465  histogram_fn);
1466  GNUNET_free (histogram_fn);
1467  }
1468  logger_test = GNUNET_CLIENT_service_test ("testbed-logger",
1469  cfg,
1471  &status_cb,
1472  NULL);
1473  }
1474 #endif
1475 
1478  GNUNET_assert (NULL != pk);
1479  my_private_key = pk;
1481  if (GNUNET_OK !=
1482  GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &proof))
1483  {
1484  GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "PROOFFILE");
1485  GNUNET_free (my_private_key);
1486  my_private_key = NULL;
1488  return;
1489  }
1490  if ((GNUNET_YES != GNUNET_DISK_file_test (proof)) ||
1491  (sizeof(my_proof) !=
1492  GNUNET_DISK_fn_read (proof, &my_proof, sizeof(my_proof))))
1493  my_proof = 0;
1494  GNUNET_free (proof);
1495  proof_task =
1497  &find_proof,
1498  NULL);
1499 
1502  /* Connect to core service and register core handlers */
1503  core_api =
1504  GNUNET_CORE_connect (cfg, /* Main configuration */
1505  NULL, /* Closure passed to functions */
1506  &core_init, /* Call core_init once connected */
1507  &handle_core_connect, /* Handle connects */
1508  &handle_core_disconnect, /* Handle disconnects */
1509  core_handlers); /* Register these handlers */
1510  if (NULL == core_api)
1511  {
1513  return;
1514  }
1515  stats = GNUNET_STATISTICS_create ("nse", cfg);
1516 }
1517 
1518 
1527 static void *
1529  struct GNUNET_SERVICE_Client *c,
1530  struct GNUNET_MQ_Handle *mq)
1531 {
1532  (void) cls;
1533  (void) mq;
1534  return c;
1535 }
1536 
1537 
1545 static void
1547  struct GNUNET_SERVICE_Client *c,
1548  void *internal_cls)
1549 {
1550  (void) cls;
1551  GNUNET_assert (c == internal_cls);
1552 }
1553 
1554 
1558 GNUNET_SERVICE_MAIN ("nse",
1560  &run,
1563  NULL,
1566  struct GNUNET_MessageHeader,
1567  NULL),
1569 
1570 
1571 #if defined(__linux__) && defined(__GLIBC__)
1572 #include <malloc.h>
1573 
1577 void __attribute__ ((constructor))
1578 GNUNET_ARM_memory_init ()
1579 {
1580  mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1581  mallopt (M_TOP_PAD, 1 * 1024);
1582  malloc_trim (0);
1583 }
1584 
1585 
1586 #endif
1587 
1588 
1589 /* 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:544
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:666
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:75
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:673
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.
static struct GNUNET_REVOCATION_PowP proof_of_work
Proof-of-work object.
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:77
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:116
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:1199
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2436
struct GNUNET_TIME_AbsoluteNBO timestamp
Timestamp at which the server received the message.
Definition: nse.h:57
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:1331
struct GNUNET_CRYPTO_EcdsaPrivateKey pk
Private key from command line option, or NULL.
int GNUNET_BIO_write_int64(struct GNUNET_BIO_WriteHandle *h, const char *what, int64_t i)
Write an (u)int64_t.
Definition: bio.c:956
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:289
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.
#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.
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:819
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:47
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.
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 ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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 HISTORY_SIZE
Over how many values do we calculate the weighted average?
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:395
#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:531
static struct GNUNET_TIME_Relative gnunet_nse_interval
Interval for sending network size estimation flood requests.
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:160
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:879
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:184
Handle to a client that is connected to a service.
Definition: service.c:250
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:1269
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:1223
static uint32_t hop_count_max
Current hop counter estimate (estimate for network diameter).
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:48
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:48
double std_deviation
The standard deviation (rounded down to the nearest integer) of size estimations. ...
Definition: nse.h:69
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:95
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 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:702
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]
#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:516
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 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.
void GNUNET_CRYPTO_pow_hash(const struct GNUNET_CRYPTO_PowSalt *salt, const void *buf, size_t buf_len, struct GNUNET_HashCode *result)
Calculate the &#39;proof-of-work&#39; hash (an expensive hash).
Definition: crypto_pow.c:41
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open_file(const char *fn)
Open a file for writing.
Definition: bio.c:559
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:67
uint64_t proof_of_work
Proof of work, causing leading zeros when hashed with pkey.
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:692
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:730
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.
int GNUNET_BIO_write_close(struct GNUNET_BIO_WriteHandle *h, char **emsg)
Close an IO handle.
Definition: bio.c:608
Value for a salt for GNUNET_CRYPTO_pow_hash().
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:62
#define ROUND_SIZE
#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:193
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:121
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:85
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.
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
#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:1083
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:189
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:84
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.
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:707
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
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...
int GNUNET_CRYPTO_hash_get_bit_ltr(const struct GNUNET_HashCode *code, unsigned int bit)
Obtain a bit from a hashcode.
Definition: crypto_hash.c:252
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.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:137
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
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:757
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:1246
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:657
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:2242
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:74
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:794
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
uint32_t reserved
For alignment.
Definition: nse.h:52
#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:972
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...