GNUnet  0.19.2
gnunet-service-dht_neighbours.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2017, 2021, 2022 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_signatures.h"
31 #include "gnunet_hello_lib.h"
32 #include "gnunet_hello_uri_lib.h"
33 #include "gnunet-service-dht.h"
36 #include "dht.h"
37 
38 #define LOG_TRAFFIC(kind, ...) GNUNET_log_from (kind, "dht-traffic", \
39  __VA_ARGS__)
40 
52 #define SANITY_CHECKS 2
53 
57 #define MAX_BUCKETS sizeof(struct GNUNET_HashCode) * 8
58 
62 #define DEFAULT_BUCKET_SIZE 8
63 
67 #define FIND_PEER_REPLICATION_LEVEL 4
68 
72 #define MAXIMUM_PENDING_PER_PEER 64
73 
79 #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
80  GNUNET_TIME_UNIT_MINUTES, 2)
81 
82 
92 #define DHT_AVG_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
93  GNUNET_TIME_UNIT_SECONDS, 6)
94 
98 #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
99 
100 
102 
107 {
112 
116  uint32_t type GNUNET_PACKED;
117 
122 
127 
132 
137 
142 
147 
151  struct GNUNET_HashCode key;
152 
153  /* trunc_peer (if truncated) */
154 
155  /* put path (if tracked) */
156 
157  /* sender_sig (if path tracking is on) */
158 
159  /* Payload */
160 };
161 
162 
167 {
172 
176  uint32_t type GNUNET_PACKED;
177 
182 
187 
192 
197 
202 
206  struct GNUNET_HashCode key;
207 
208  /* trunc_peer (if truncated) */
209 
210  /* put path (if tracked) */
211 
212  /* get path (if tracked) */
213 
214  /* sender_sig (if path tracking is on) */
215 
216  /* Payload */
217 };
218 
219 
224 {
229 
233  uint32_t type GNUNET_PACKED;
234 
239 
244 
249 
254 
259 
263  struct GNUNET_HashCode key;
264 
265  /* result bloomfilter */
266 
267  /* xquery */
268 
269 };
271 
272 
276 struct PeerInfo;
277 
278 
282 struct Target
283 {
287  struct Target *next;
288 
292  struct Target *prev;
293 
298 
302  struct GDS_Underlay *u;
303 
307  struct PeerInfo *pi;
308 
313 
317  unsigned int load;
318 
323  bool dropped;
324 
325 };
326 
327 
331 struct PeerInfo
332 {
336  struct GNUNET_PeerIdentity id;
337 
341  struct GNUNET_HashCode phash;
342 
347 
351  struct PeerInfo *next;
352 
356  struct PeerInfo *prev;
357 
361  struct Target *t_head;
362 
366  struct Target *t_tail;
367 
371  void *hello;
372 
376  size_t hello_size;
377 
382 };
383 
384 
389 {
393  struct PeerInfo *head;
394 
398  struct PeerInfo *tail;
399 
403  unsigned int peers_size;
404 };
405 
406 
410 static int cache_results;
411 
415 static unsigned int closest_bucket;
416 
421 static unsigned int newly_found_peers;
422 
427 
431 static struct PeerBucket k_buckets[MAX_BUCKETS];
432 
438 
442 static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
443 
448 
449 
457 static void
458 send_done_cb (void *cls)
459 {
460  struct Target *t = cls;
461  struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
462 
463  GNUNET_assert (t->load > 0);
464  t->load--;
465  if (0 < t->load)
466  return;
467  if (t->dropped)
468  {
469  GNUNET_free (t);
470  return;
471  }
472  /* move target back to the front */
474  pi->t_tail,
475  t);
477  pi->t_tail,
478  t);
479 }
480 
481 
488 static void
489 do_send (struct PeerInfo *pi,
490  const struct GNUNET_MessageHeader *msg)
491 {
492  struct Target *t;
493 
494  for (t = pi->t_head;
495  NULL != t;
496  t = t->next)
497  if (t->load < MAXIMUM_PENDING_PER_PEER)
498  break;
499  if (NULL == t)
500  {
501  /* all targets busy, drop message */
503  "# messages dropped (underlays busy)",
504  1,
505  GNUNET_NO);
506  return;
507  }
508  t->load++;
509  /* rotate busy targets to the end */
510  if (MAXIMUM_PENDING_PER_PEER == t->load)
511  {
513  pi->t_tail,
514  t);
516  pi->t_tail,
517  t);
518  }
519  GDS_u_send (t->u,
520  t->utarget,
521  msg,
522  ntohs (msg->size),
523  &send_done_cb,
524  t);
525 }
526 
527 
540 static void
541 sign_path (const void *data,
542  size_t data_size,
543  struct GNUNET_TIME_Absolute exp_time,
544  const struct GNUNET_PeerIdentity *pred,
545  const struct GNUNET_PeerIdentity *succ,
546  struct GNUNET_CRYPTO_EddsaSignature *sig)
547 {
548  struct GNUNET_DHT_HopSignature hs = {
550  .purpose.size = htonl (sizeof (hs)),
551  .expiration_time = GNUNET_TIME_absolute_hton (exp_time),
552  .succ = *succ
553  };
554 
555  if (NULL != pred)
556  hs.pred = *pred;
558  data_size,
559  &hs.h_data);
561  &hs,
562  sig);
563 }
564 
565 
573 static int
574 find_bucket (const struct GNUNET_HashCode *hc)
575 {
576  struct GNUNET_HashCode xor;
577  unsigned int bits;
578 
581  &xor);
583  if (bits == MAX_BUCKETS)
584  {
585  /* How can all bits match? Got my own ID? */
586  GNUNET_break (0);
587  return -1;
588  }
589  return MAX_BUCKETS - bits - 1;
590 }
591 
592 
602 static enum GNUNET_GenericReturnValue
603 add_known_to_bloom (void *cls,
604  const struct GNUNET_PeerIdentity *key,
605  void *value)
606 {
607  struct GNUNET_BLOCK_Group *bg = cls;
608  struct PeerInfo *pi = value;
609 
611  &pi->phash,
612  1);
614  "Adding known peer (%s) to Bloom filter for FIND PEER\n",
615  GNUNET_i2s (key));
616  return GNUNET_YES;
617 }
618 
619 
627 static void
629 {
630  (void) cls;
631 
632  /* Compute when to do this again (and if we should
633  even send a message right now) */
634  {
635  struct GNUNET_TIME_Relative next_send_time;
636  bool done_early;
637 
638  find_peer_task = NULL;
639  done_early = (newly_found_peers > bucket_size);
640  /* schedule next round, taking longer if we found more peers
641  in the last round. */
642  next_send_time.rel_value_us =
643  DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us
648  1 + 100 * (1 + newly_found_peers) / bucket_size).rel_value_us);
649  newly_found_peers = 0;
650  GNUNET_assert (NULL == find_peer_task);
652  GNUNET_SCHEDULER_add_delayed (next_send_time,
654  NULL);
655  if (done_early)
656  return;
657  }
658 
659  /* actually send 'find peer' request */
660  {
661  struct GNUNET_BLOCK_Group *bg;
662  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
663 
666  NULL,
667  0,
668  "set-seen-size",
670  NULL);
673  bg);
674  peer_bf
678  if (GNUNET_OK !=
683  0, /* hop count */
685  NULL, 0, /* xquery */
686  bg,
687  peer_bf))
688  {
690  "# Failed to initiate FIND PEER lookup",
691  1,
692  GNUNET_NO);
693  }
694  else
695  {
697  "# FIND PEER messages initiated",
698  1,
699  GNUNET_NO);
700  }
703  }
704 }
705 
706 
714 static void
715 update_hold (struct PeerBucket *bucket)
716 {
717  unsigned int off = 0;
718 
719  /* find the peer -- we just go over all of them, should
720  be hardly any more expensive than just finding the 'right'
721  one. */
722  for (struct PeerInfo *pos = bucket->head;
723  NULL != pos;
724  pos = pos->next)
725  {
726  if (off > bucket_size)
727  break; /* We only hold up to #bucket_size peers per bucket */
728  off++;
729  for (struct Target *tp = pos->t_head;
730  NULL != tp;
731  tp = tp->next)
732  if (NULL == tp->ph)
733  tp->ph = GDS_u_hold (tp->u,
734  tp->utarget);
735  }
736 }
737 
738 
739 void
740 GDS_u_connect (void *cls,
741  struct GNUNET_DHTU_Target *target,
742  const struct GNUNET_PeerIdentity *pid,
743  void **ctx)
744 {
745  struct GDS_Underlay *u = cls;
746  struct PeerInfo *pi;
747  struct PeerBucket *bucket;
748  bool do_hold = false;
749 
750  /* Check for connect to self message */
751  if (0 == GNUNET_memcmp (&GDS_my_identity,
752  pid))
753  return;
755  "Connected to peer %s\n",
756  GNUNET_i2s (pid));
758  pid);
759  if (NULL == pi)
760  {
762  "# peers connected",
763  1,
764  GNUNET_NO);
765  pi = GNUNET_new (struct PeerInfo);
766  pi->id = *pid;
768  sizeof(*pid),
769  &pi->phash);
770  pi->peer_bucket = find_bucket (&pi->phash);
771  GNUNET_assert ( (pi->peer_bucket >= 0) &&
772  ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
773  bucket = &k_buckets[pi->peer_bucket];
775  bucket->tail,
776  pi);
777  bucket->peers_size++;
779  (unsigned int) pi->peer_bucket + 1);
782  &pi->id,
783  pi,
785  if (bucket->peers_size <= bucket_size)
786  {
788  do_hold = true;
789  }
792  {
793  /* got a first connection, good time to start with FIND PEER requests... */
794  GNUNET_assert (NULL == find_peer_task);
796  NULL);
797  }
798  }
799  {
800  struct Target *t;
801 
802  t = GNUNET_new (struct Target);
803  t->u = u;
804  t->utarget = target;
805  t->pi = pi;
807  pi->t_tail,
808  t);
809  *ctx = t;
810 
811  }
812  if (do_hold)
813  update_hold (bucket);
814 }
815 
816 
817 void
819 {
820  struct Target *t = ctx;
821  struct PeerInfo *pi;
822  struct PeerBucket *bucket;
823  bool was_held = false;
824 
825  /* Check for disconnect from self message (on shutdown) */
826  if (NULL == t)
827  return;
828  pi = t->pi;
830  pi->t_tail,
831  t);
832  if (NULL != t->ph)
833  {
834  GDS_u_drop (t->u,
835  t->ph);
836  t->ph = NULL;
837  was_held = true;
838  }
839  if (t->load > 0)
840  {
841  t->dropped = true;
842  t->pi = NULL;
843  }
844  else
845  {
846  GNUNET_free (t);
847  }
848  if (NULL != pi->t_head)
849  return; /* got other connections still */
851  "Disconnected from peer %s\n",
852  GNUNET_i2s (&pi->id));
854  "# peers connected",
855  -1,
856  GNUNET_NO);
859  &pi->id,
860  pi));
863  {
865  find_peer_task = NULL;
866  }
867  GNUNET_assert (pi->peer_bucket >= 0);
868  bucket = &k_buckets[pi->peer_bucket];
870  bucket->tail,
871  pi);
872  GNUNET_assert (bucket->peers_size > 0);
873  bucket->peers_size--;
874  if ( (was_held) &&
875  (bucket->peers_size >= bucket_size - 1) )
876  update_hold (bucket);
877  while ( (closest_bucket > 0) &&
878  (0 == k_buckets[closest_bucket - 1].peers_size))
879  closest_bucket--;
880  GNUNET_free (pi->hello);
881  GNUNET_free (pi);
882 }
883 
884 
893 static unsigned int
894 get_forward_count (uint16_t hop_count,
895  uint16_t target_replication)
896 {
897  uint32_t random_value;
898  uint32_t forward_count;
899  float target_value;
900  float rm1;
901 
902  if (hop_count > GDS_NSE_get () * 4.0)
903  {
904  /* forcefully terminate */
906  "# requests TTL-dropped",
907  1,
908  GNUNET_NO);
909  return 0;
910  }
911  if (hop_count > GDS_NSE_get () * 2.0)
912  {
913  /* Once we have reached our ideal number of hops, only forward to 1 peer */
914  return 1;
915  }
916  /* bound by system-wide maximum and minimum */
917  if (0 == target_replication)
918  target_replication = 1; /* 0 is verboten */
919  target_replication =
921  target_replication);
922  rm1 = target_replication - 1.0;
923  target_value =
924  1 + (rm1) / (GDS_NSE_get () + (rm1 * hop_count));
925 
926  /* Set forward count to floor of target_value */
927  forward_count = (uint32_t) target_value;
928  /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
929  target_value = target_value - forward_count;
931  UINT32_MAX);
932  if (random_value < (target_value * UINT32_MAX))
933  forward_count++;
934  return GNUNET_MIN (forward_count,
936 }
937 
938 
951  const struct GNUNET_CONTAINER_BloomFilter *bloom)
952 {
954  key))
955  return GNUNET_YES;
956  for (int bucket_num = find_bucket (key);
957  bucket_num < closest_bucket;
958  bucket_num++)
959  {
960  unsigned int count = 0;
961 
962  GNUNET_assert (bucket_num >= 0);
963  for (struct PeerInfo *pos = k_buckets[bucket_num].head;
964  NULL != pos;
965  pos = pos->next)
966  {
967  if (count >= bucket_size)
968  break; /* we only consider first #bucket_size entries per bucket */
969  count++;
970  if ( (NULL != bloom) &&
971  (GNUNET_YES ==
973  &pos->phash)) )
974  continue; /* Ignore filtered peers */
975  /* All peers in this bucket must be closer than us, as
976  they mismatch with our PID on the pivotal bit. So
977  because an unfiltered peer exists, we are not the
978  closest. */
979  int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
981  key);
982  switch (delta)
983  {
984  case -1: /* pos closer */
985  return GNUNET_NO;
986  case 0: /* identical, impossible! */
987  GNUNET_assert (0);
988  break;
989  case 1: /* I am closer */
990  break;
991  }
992  }
993  }
994  /* No closer (unfiltered) peers found; we must be the closest! */
995  return GNUNET_YES;
996 }
997 
998 
1020 static struct PeerInfo *
1022  const struct GNUNET_CONTAINER_BloomFilter *bloom,
1023  uint32_t hops)
1024 {
1025  if (0 == closest_bucket)
1026  {
1028  "# Peer selection failed",
1029  1,
1030  GNUNET_NO);
1031  return NULL; /* we have zero connections */
1032  }
1033  if (hops >= GDS_NSE_get ())
1034  {
1035  /* greedy selection (closest peer that is not in Bloom filter) */
1036  struct PeerInfo *chosen = NULL;
1037  int best_bucket;
1038  int bucket_offset;
1039 
1040  {
1041  struct GNUNET_HashCode xor;
1042 
1045  &xor);
1046  best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
1047  }
1048  if (best_bucket >= closest_bucket)
1049  bucket_offset = closest_bucket - 1;
1050  else
1051  bucket_offset = best_bucket;
1052  while (-1 != bucket_offset)
1053  {
1054  struct PeerBucket *bucket = &k_buckets[bucket_offset];
1055  unsigned int count = 0;
1056 
1057  for (struct PeerInfo *pos = bucket->head;
1058  NULL != pos;
1059  pos = pos->next)
1060  {
1061  if (count >= bucket_size)
1062  break; /* we only consider first #bucket_size entries per bucket */
1063  count++;
1064  if ( (NULL != bloom) &&
1065  (GNUNET_YES ==
1067  &pos->phash)) )
1068  {
1070  "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1071  GNUNET_i2s (&pos->id),
1072  GNUNET_h2s (key));
1073  continue;
1074  }
1075  if (NULL == chosen)
1076  {
1077  /* First candidate */
1078  chosen = pos;
1079  }
1080  else
1081  {
1082  int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
1083  &chosen->phash,
1084  key);
1085  switch (delta)
1086  {
1087  case -1: /* pos closer */
1088  chosen = pos;
1089  break;
1090  case 0: /* identical, impossible! */
1091  GNUNET_assert (0);
1092  break;
1093  case 1: /* chosen closer */
1094  break;
1095  }
1096  }
1097  count++;
1098  } /* for all (#bucket_size) peers in bucket */
1099  if (NULL != chosen)
1100  break;
1101 
1102  /* If we chose nothing in first iteration, first go through deeper
1103  buckets (best chance to find a good match), and if we still found
1104  nothing, then to shallower buckets. Terminate on any match in the
1105  current bucket, as this search order guarantees that it can only get
1106  worse as we keep going. */
1107  if (bucket_offset > best_bucket)
1108  {
1109  /* Go through more deeper buckets */
1110  bucket_offset++;
1111  if (bucket_offset == closest_bucket)
1112  {
1113  /* Can't go any deeper, if nothing selected,
1114  go for shallower buckets */
1115  bucket_offset = best_bucket - 1;
1116  }
1117  }
1118  else
1119  {
1120  /* We're either at the 'best_bucket' or already moving
1121  on to shallower buckets. */
1122  if (bucket_offset == best_bucket)
1123  bucket_offset++; /* go for deeper buckets */
1124  else
1125  bucket_offset--; /* go for shallower buckets */
1126  }
1127  } /* for applicable buckets (starting at best match) */
1128  if (NULL == chosen)
1129  {
1131  "# Peer selection failed",
1132  1,
1133  GNUNET_NO);
1134  return NULL;
1135  }
1137  "Selected peer `%s' in greedy routing for %s\n",
1138  GNUNET_i2s (&chosen->id),
1139  GNUNET_h2s (key));
1140  return chosen;
1141  } /* end of 'greedy' peer selection */
1142 
1143  /* select "random" peer */
1144  /* count number of peers that are available and not filtered,
1145  but limit to at most #bucket_size peers, starting with
1146  those 'furthest' from us. */
1147  {
1148  unsigned int total = 0;
1149  unsigned int selected;
1150 
1151  for (unsigned int bc = 0; bc < closest_bucket; bc++)
1152  {
1153  struct PeerBucket *bucket = &k_buckets[bc];
1154  unsigned int count = 0;
1155 
1156  for (struct PeerInfo *pos = bucket->head;
1157  NULL != pos;
1158  pos = pos->next)
1159  {
1160  count++;
1161  if (count > bucket_size)
1162  break; /* limits search to #bucket_size peers per bucket */
1163  if ( (NULL != bloom) &&
1164  (GNUNET_YES ==
1166  &pos->phash)) )
1167  {
1169  "Excluded peer `%s' due to BF match in random routing for %s\n",
1170  GNUNET_i2s (&pos->id),
1171  GNUNET_h2s (key));
1172  continue; /* Ignore filtered peers */
1173  }
1174  total++;
1175  } /* for all peers in bucket */
1176  } /* for all buckets */
1177  if (0 == total) /* No peers to select from! */
1178  {
1180  "# Peer selection failed",
1181  1,
1182  GNUNET_NO);
1183  return NULL;
1184  }
1185 
1186  /* Now actually choose a peer */
1188  total);
1189  for (unsigned int bc = 0; bc < closest_bucket; bc++)
1190  {
1191  unsigned int count = 0;
1192 
1193  for (struct PeerInfo *pos = k_buckets[bc].head;
1194  pos != NULL;
1195  pos = pos->next)
1196  {
1197  count++;
1198  if (count > bucket_size)
1199  break; /* limits search to #bucket_size peers per bucket */
1200 
1201  if ( (NULL != bloom) &&
1202  (GNUNET_YES ==
1204  &pos->phash)) )
1205  continue; /* Ignore bloomfiltered peers */
1206  if (0 == selected--)
1207  {
1209  "Selected peer `%s' in random routing for %s\n",
1210  GNUNET_i2s (&pos->id),
1211  GNUNET_h2s (key));
1212  return pos;
1213  }
1214  } /* for peers in bucket */
1215  } /* for all buckets */
1216  } /* random peer selection scope */
1217  GNUNET_break (0);
1218  return NULL;
1219 }
1220 
1221 
1235 static unsigned int
1237  struct GNUNET_CONTAINER_BloomFilter *bloom,
1238  uint16_t hop_count,
1239  uint16_t target_replication,
1240  struct PeerInfo ***targets)
1241 {
1242  unsigned int target;
1243  unsigned int off;
1244  struct PeerInfo **rtargets;
1245 
1246  GNUNET_assert (NULL != bloom);
1247  target = get_forward_count (hop_count,
1248  target_replication);
1249  if (0 == target)
1250  {
1251  *targets = NULL;
1252  return 0;
1253  }
1254  rtargets = GNUNET_new_array (target,
1255  struct PeerInfo *);
1256  for (off = 0; off < target; off++)
1257  {
1258  struct PeerInfo *nxt;
1259 
1260  nxt = select_peer (key,
1261  bloom,
1262  hop_count);
1263  if (NULL == nxt)
1264  break;
1265  rtargets[off] = nxt;
1268  &nxt->phash));
1270  &nxt->phash);
1271  }
1273  "Selected %u/%u peers at hop %u for %s (target was %u)\n",
1274  off,
1276  (unsigned int) hop_count,
1277  GNUNET_h2s (key),
1278  target);
1279  if (0 == off)
1280  {
1281  GNUNET_free (rtargets);
1282  *targets = NULL;
1283  return 0;
1284  }
1285  *targets = rtargets;
1287  "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1288  GNUNET_h2s (key),
1289  off,
1290  target);
1291  return off;
1292 }
1293 
1294 
1300 static void
1302 {
1303  struct GNUNET_PeerIdentity pid;
1304  struct GNUNET_HELLO_Builder *b;
1305 
1306  if (GNUNET_BLOCK_TYPE_DHT_HELLO != bd->type)
1307  return;
1308 
1310  bd->data_size);
1313  &pid,
1314  &GDS_try_connect,
1315  &pid);
1317 }
1318 
1319 
1322  uint16_t desired_replication_level,
1323  uint16_t hop_count,
1324  struct GNUNET_CONTAINER_BloomFilter *bf)
1325 {
1326  unsigned int target_count;
1327  struct PeerInfo **targets;
1328  size_t msize;
1329  unsigned int skip_count;
1330  enum GNUNET_DHT_RouteOption ro = bd->ro;
1331  unsigned int put_path_length = bd->put_path_length;
1332  const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
1333  bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1334  bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1335  const struct GNUNET_PeerIdentity *trunc_peer
1336  = truncated
1337  ? &bd->trunc_peer
1338  : NULL;
1339 
1340 #if SANITY_CHECKS > 1
1341  unsigned int failure_offset;
1342 
1343  failure_offset
1345  bd->data_size,
1346  bd->expiration_time,
1347  trunc_peer,
1348  put_path,
1349  put_path_length,
1350  NULL, 0, /* get_path */
1351  &GDS_my_identity);
1352  if (0 != failure_offset)
1353  {
1354  GNUNET_break_op (0);
1355  truncated = true;
1356  trunc_peer = &put_path[failure_offset - 1].pred;
1357  put_path = &put_path[failure_offset];
1358  put_path_length = put_path_length - failure_offset;
1360  }
1361 #endif
1363  "Adding myself (%s) to PUT bloomfilter for %s with RO(%s/%s)\n",
1365  GNUNET_h2s (&bd->key),
1366  (bd->ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1367  (bd->ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1368 
1369  /* if we got a HELLO, consider it for our own routing table */
1370  hello_check (bd);
1371  GNUNET_assert (NULL != bf);
1375  "# PUT requests routed",
1376  1,
1377  GNUNET_NO);
1378  if (bd->data_size
1380  - sizeof(struct PeerPutMessage))
1381  {
1382  GNUNET_break (0);
1383  return GNUNET_SYSERR;
1384  }
1385  msize = bd->data_size + sizeof(struct PeerPutMessage);
1386  if (tracking)
1387  {
1388  if (msize + sizeof (struct GNUNET_CRYPTO_EddsaSignature)
1390  {
1392  "Discarding message that is too large due to tracking\n");
1393  return GNUNET_NO;
1394  }
1395  msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
1396  }
1397  else
1398  {
1399  /* If tracking is disabled, also discard any path we might have
1400  gotten from some broken peer */
1401  GNUNET_break_op (0 == put_path_length);
1402  put_path_length = 0;
1403  }
1404  if (truncated)
1405  msize += sizeof (struct GNUNET_PeerIdentity);
1406  if (msize + put_path_length * sizeof(struct GNUNET_DHT_PathElement)
1408  {
1409  unsigned int mlen;
1410  unsigned int ppl;
1411 
1413  "Truncating path that is too large due\n");
1415  if (! truncated)
1416  {
1417  /* We need extra space for the truncation, consider that,
1418  too! */
1419  truncated = true;
1420  mlen -= sizeof (struct GNUNET_PeerIdentity);
1421  msize += sizeof (struct GNUNET_PeerIdentity);
1422  }
1423  /* compute maximum length of path we can keep */
1424  ppl = mlen / sizeof (struct GNUNET_DHT_PathElement);
1425  GNUNET_assert (put_path_length - ppl > 0);
1426  trunc_peer = &put_path[put_path_length - ppl - 1].pred;
1427  put_path = &put_path[put_path_length - ppl];
1428  put_path_length = ppl;
1430  }
1431  else
1432  {
1433  msize += bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement);
1434  }
1435  target_count
1436  = get_target_peers (&bd->key,
1437  bf,
1438  hop_count,
1439  desired_replication_level,
1440  &targets);
1441  if (0 == target_count)
1442  {
1444  "Routing PUT for %s terminates after %u hops at %s\n",
1445  GNUNET_h2s (&bd->key),
1446  (unsigned int) hop_count,
1448  return GNUNET_NO;
1449  }
1450  skip_count = 0;
1451  for (unsigned int i = 0; i < target_count; i++)
1452  {
1453  struct PeerInfo *target = targets[i];
1454  struct PeerPutMessage *ppm;
1455  char buf[msize] GNUNET_ALIGN;
1456  struct GNUNET_DHT_PathElement *pp;
1457  void *data;
1458 
1460  "Routing PUT for %s after %u hops to %s\n",
1461  GNUNET_h2s (&bd->key),
1462  (unsigned int) hop_count,
1463  GNUNET_i2s (&target->id));
1464  ppm = (struct PeerPutMessage *) buf;
1466  ppm->header.size = htons (sizeof (buf));
1467  ppm->type = htonl (bd->type);
1468  ppm->options = htons (ro);
1469  ppm->hop_count = htons (hop_count + 1);
1471  ppm->put_path_length = htons (put_path_length);
1475  &target->phash));
1478  ppm->bloomfilter,
1479  DHT_BLOOM_SIZE));
1480  ppm->key = bd->key;
1481  if (truncated)
1482  {
1483  void *tgt = &ppm[1];
1484 
1485  GNUNET_memcpy (tgt,
1486  trunc_peer,
1487  sizeof (struct GNUNET_PeerIdentity));
1488  pp = (struct GNUNET_DHT_PathElement *)
1489  (tgt + sizeof (struct GNUNET_PeerIdentity));
1490  }
1491  else
1492  {
1493  pp = (struct GNUNET_DHT_PathElement *) &ppm[1];
1494  }
1495  GNUNET_memcpy (pp,
1496  put_path,
1497  sizeof (struct GNUNET_DHT_PathElement) * put_path_length);
1498  if (tracking)
1499  {
1500  void *tgt = &pp[put_path_length];
1501  struct GNUNET_CRYPTO_EddsaSignature last_sig;
1502 
1503  if (0 == put_path_length)
1504  {
1505  /* Note that the signature in 'put_path' was not initialized before,
1506  so this is crucial to avoid sending garbage. */
1507  sign_path (bd->data,
1508  bd->data_size,
1509  bd->expiration_time,
1510  trunc_peer,
1511  &target->id,
1512  &last_sig);
1513  }
1514  else
1515  {
1516  sign_path (bd->data,
1517  bd->data_size,
1518  bd->expiration_time,
1519  &pp[put_path_length - 1].pred,
1520  &target->id,
1521  &last_sig);
1522  }
1524  "Signing PUT PATH %u => %s\n",
1525  put_path_length,
1526  GNUNET_B2S (&last_sig));
1527  memcpy (tgt,
1528  &last_sig,
1529  sizeof (last_sig));
1530  data = tgt + sizeof (last_sig);
1531  }
1532  else /* ! tracking */
1533  {
1534  data = &ppm[1];
1535  }
1537  bd->data,
1538  bd->data_size);
1539  do_send (target,
1540  &ppm->header);
1541  }
1542  GNUNET_free (targets);
1544  "# PUT messages queued for transmission",
1545  target_count - skip_count,
1546  GNUNET_NO);
1547  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1548 }
1549 
1550 
1554  uint16_t desired_replication_level,
1555  uint16_t hop_count,
1556  const struct GNUNET_HashCode *key,
1557  const void *xquery,
1558  size_t xquery_size,
1559  struct GNUNET_BLOCK_Group *bg,
1560  struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1561 {
1562  unsigned int target_count;
1563  struct PeerInfo **targets;
1564  size_t msize;
1565  size_t result_filter_size;
1566  void *result_filter;
1567  unsigned int skip_count;
1568 
1569  GNUNET_assert (NULL != peer_bf);
1571  "# GET requests routed",
1572  1,
1573  GNUNET_NO);
1574  target_count = get_target_peers (key,
1575  peer_bf,
1576  hop_count,
1577  desired_replication_level,
1578  &targets);
1580  "Adding myself (%s) to GET bloomfilter for %s with RO(%s/%s)\n",
1582  GNUNET_h2s (key),
1584  (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1585 
1588  if (0 == target_count)
1589  {
1591  "Routing GET for %s terminates after %u hops at %s\n",
1592  GNUNET_h2s (key),
1593  (unsigned int) hop_count,
1595  return GNUNET_NO;
1596  }
1597  if (GNUNET_OK !=
1599  &result_filter,
1600  &result_filter_size))
1601  {
1602  result_filter = NULL;
1603  result_filter_size = 0;
1604  }
1605  msize = xquery_size + result_filter_size;
1606  if (msize + sizeof(struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
1607  {
1608  GNUNET_break (0);
1609  GNUNET_free (result_filter);
1610  GNUNET_free (targets);
1611  return GNUNET_NO;
1612  }
1613  /* forward request */
1614  skip_count = 0;
1615  for (unsigned int i = 0; i < target_count; i++)
1616  {
1617  struct PeerInfo *target = targets[i];
1618  struct PeerGetMessage *pgm;
1619  char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
1620  char *rf;
1621 
1623  "Routing GET for %s after %u hops to %s\n",
1624  GNUNET_h2s (key),
1625  (unsigned int) hop_count,
1626  GNUNET_i2s (&target->id));
1627  pgm = (struct PeerGetMessage *) buf;
1629  pgm->header.size = htons (sizeof (buf));
1630  pgm->type = htonl (type);
1631  pgm->options = htons (options);
1632  pgm->hop_count = htons (hop_count + 1);
1634  pgm->result_filter_size = htons ((uint16_t) result_filter_size);
1637  &target->phash));
1640  pgm->bloomfilter,
1641  DHT_BLOOM_SIZE));
1642  pgm->key = *key;
1643  rf = (char *) &pgm[1];
1644  GNUNET_memcpy (rf,
1645  result_filter,
1648  xquery,
1649  xquery_size);
1650  do_send (target,
1651  &pgm->header);
1652  }
1654  "# GET messages queued for transmission",
1655  target_count - skip_count,
1656  GNUNET_NO);
1657  GNUNET_free (targets);
1658  GNUNET_free (result_filter);
1659  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1660 }
1661 
1662 
1663 struct PeerInfo *
1665 {
1667  target);
1668 }
1669 
1670 
1671 bool
1673  const struct GNUNET_DATACACHE_Block *bd,
1674  const struct GNUNET_HashCode *query_hash,
1675  unsigned int get_path_length,
1676  const struct GNUNET_DHT_PathElement *get_path)
1677 {
1678  struct GNUNET_DHT_PathElement *paths;
1679  size_t msize;
1680  unsigned int ppl = bd->put_path_length;
1681  const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
1682  enum GNUNET_DHT_RouteOption ro = bd->ro;
1683  bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1684  const struct GNUNET_PeerIdentity *trunc_peer
1685  = truncated
1686  ? &bd->trunc_peer
1687  : NULL;
1688  bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1689 #if SANITY_CHECKS > 1
1690  unsigned int failure_offset;
1691 
1692  failure_offset
1694  bd->data_size,
1695  bd->expiration_time,
1696  trunc_peer,
1697  put_path,
1698  ppl,
1699  get_path,
1700  get_path_length,
1701  &GDS_my_identity);
1702  if (0 != failure_offset)
1703  {
1704  GNUNET_assert (failure_offset <= ppl + get_path_length);
1705  GNUNET_break_op (0);
1706  if (failure_offset < ppl)
1707  {
1708  trunc_peer = &put_path[failure_offset - 1].pred;
1709  put_path += failure_offset;
1710  ppl -= failure_offset;
1711  truncated = true;
1713  }
1714  else
1715  {
1716  failure_offset -= ppl;
1717  if (0 == failure_offset)
1718  trunc_peer = &put_path[ppl - 1].pred;
1719  else
1720  trunc_peer = &get_path[failure_offset - 1].pred;
1721  ppl = 0;
1722  put_path = NULL;
1723  truncated = true;
1725  get_path += failure_offset;
1726  get_path_length -= failure_offset;
1727  }
1728  }
1729 #endif
1730  msize = bd->data_size + sizeof (struct PeerResultMessage);
1731  if (msize > GNUNET_MAX_MESSAGE_SIZE)
1732  {
1733  GNUNET_break_op (0);
1734  return false;
1735  }
1736  if (truncated)
1737  msize += sizeof (struct GNUNET_PeerIdentity);
1738  if (tracking)
1739  msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
1740  if (msize < bd->data_size)
1741  {
1742  GNUNET_break_op (0);
1743  return false;
1744  }
1745  if ( (GNUNET_MAX_MESSAGE_SIZE - msize)
1746  / sizeof(struct GNUNET_DHT_PathElement)
1747  < (get_path_length + ppl) )
1748  {
1749  get_path_length = 0;
1750  ppl = 0;
1751  }
1752  if ( (get_path_length > UINT16_MAX) ||
1753  (ppl > UINT16_MAX) )
1754  {
1755  GNUNET_break (0);
1756  get_path_length = 0;
1757  ppl = 0;
1758  }
1759  msize += (get_path_length + ppl)
1760  * sizeof(struct GNUNET_DHT_PathElement);
1762  "Forwarding reply for key %s to peer %s\n",
1763  GNUNET_h2s (query_hash),
1764  GNUNET_i2s (&pi->id));
1766  "# RESULT messages queued for transmission",
1767  1,
1768  GNUNET_NO);
1769  {
1770  struct PeerResultMessage *prm;
1771  char buf[msize] GNUNET_ALIGN;
1772  void *data;
1773 
1774  prm = (struct PeerResultMessage *) buf;
1776  prm->header.size = htons (sizeof (buf));
1777  prm->type = htonl ((uint32_t) bd->type);
1778  prm->reserved = htons (0);
1779  prm->options = htons ((uint16_t) ro);
1780  prm->put_path_length = htons ((uint16_t) ppl);
1781  prm->get_path_length = htons ((uint16_t) get_path_length);
1783  prm->key = *query_hash;
1784  if (truncated)
1785  {
1786  void *tgt = &prm[1];
1787 
1788  GNUNET_memcpy (tgt,
1789  trunc_peer,
1790  sizeof (struct GNUNET_PeerIdentity));
1791  paths = (struct GNUNET_DHT_PathElement *)
1792  (tgt + sizeof (struct GNUNET_PeerIdentity));
1793  }
1794  else
1795  {
1796  paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1797  }
1798  if (NULL != put_path)
1799  {
1800  GNUNET_memcpy (paths,
1801  put_path,
1802  ppl * sizeof(struct GNUNET_DHT_PathElement));
1803  }
1804  else
1805  {
1806  GNUNET_assert (0 == ppl);
1807  }
1808  if (NULL != get_path)
1809  {
1810  GNUNET_memcpy (&paths[ppl],
1811  get_path,
1812  get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1813  }
1814  else
1815  {
1816  GNUNET_assert (0 == get_path_length);
1817  }
1818  if (tracking)
1819  {
1820  struct GNUNET_CRYPTO_EddsaSignature sig;
1821  void *tgt = &paths[get_path_length + ppl];
1822  const struct GNUNET_PeerIdentity *pred;
1823 
1824  if (ppl + get_path_length > 0)
1825  pred = &paths[ppl + get_path_length - 1].pred;
1826  else if (truncated)
1827  pred = trunc_peer;
1828  else
1829  pred = NULL; /* we are first! */
1830  /* Note that the last signature in 'paths' was not initialized before,
1831  so this is crucial to avoid sending garbage. */
1832  sign_path (bd->data,
1833  bd->data_size,
1834  bd->expiration_time,
1835  pred,
1836  &pi->id,
1837  &sig);
1838  memcpy (tgt,
1839  &sig,
1840  sizeof (sig));
1841  data = tgt + sizeof (sig);
1843  "Signing GET PATH %u/%u of %s => %s\n",
1844  ppl,
1845  get_path_length,
1846  GNUNET_h2s (query_hash),
1847  GNUNET_B2S (&sig));
1848 #if SANITY_CHECKS > 1
1849  {
1850  struct GNUNET_DHT_PathElement xpaths[get_path_length + 1];
1851 
1852  memcpy (xpaths,
1853  &paths[ppl],
1854  get_path_length * sizeof (struct GNUNET_DHT_PathElement));
1855  xpaths[get_path_length].sig = sig;
1856  xpaths[get_path_length].pred = GDS_my_identity;
1857  if (0 !=
1859  bd->data_size,
1860  bd->expiration_time,
1861  trunc_peer,
1862  paths,
1863  ppl,
1864  xpaths,
1865  get_path_length + 1,
1866  &pi->id))
1867  {
1868  GNUNET_break (0);
1869  return false;
1870  }
1871  }
1872 #endif
1873  }
1874  else
1875  {
1876  data = &prm[1];
1877  }
1879  bd->data,
1880  bd->data_size);
1881  do_send (pi,
1882  &prm->header);
1883  }
1884  return true;
1885 }
1886 
1887 
1895 static enum GNUNET_GenericReturnValue
1896 check_dht_p2p_put (void *cls,
1897  const struct PeerPutMessage *put)
1898 {
1899  enum GNUNET_DHT_RouteOption ro
1900  = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1901  bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1902  bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1903  uint16_t msize = ntohs (put->header.size);
1904  uint16_t putlen = ntohs (put->put_path_length);
1905  size_t xsize = (has_path
1906  ? sizeof (struct GNUNET_CRYPTO_EddsaSignature)
1907  : 0)
1908  + (truncated
1909  ? sizeof (struct GNUNET_PeerIdentity)
1910  : 0);
1911  size_t var_meta_size
1912  = putlen * sizeof(struct GNUNET_DHT_PathElement)
1913  + xsize;
1914 
1915  (void) cls;
1916  if ( (msize <
1917  sizeof (struct PeerPutMessage) + var_meta_size) ||
1918  (putlen >
1919  (GNUNET_MAX_MESSAGE_SIZE
1920  - sizeof (struct PeerPutMessage)
1921  - xsize)
1922  / sizeof(struct GNUNET_DHT_PathElement)) )
1923  {
1924  GNUNET_break_op (0);
1925  return GNUNET_SYSERR;
1926  }
1927  if (GNUNET_BLOCK_TYPE_ANY == htonl (put->type))
1928  {
1929  GNUNET_break_op (0);
1930  return GNUNET_SYSERR;
1931  }
1932  return GNUNET_OK;
1933 }
1934 
1935 
1942 static void
1944  const struct PeerPutMessage *put)
1945 {
1946  struct Target *t = cls;
1947  struct PeerInfo *peer = t->pi;
1948  enum GNUNET_DHT_RouteOption ro
1949  = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1950  bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1951  bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1952  uint16_t msize = ntohs (put->header.size);
1953  uint16_t putlen = ntohs (put->put_path_length);
1954  const struct GNUNET_PeerIdentity *trunc_peer
1955  = truncated
1956  ? (const struct GNUNET_PeerIdentity *) &put[1]
1957  : NULL;
1958  const struct GNUNET_DHT_PathElement *put_path
1959  = truncated
1960  ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
1961  : (const struct GNUNET_DHT_PathElement *) &put[1];
1962  const struct GNUNET_CRYPTO_EddsaSignature *last_sig
1963  = has_path
1964  ? (const struct GNUNET_CRYPTO_EddsaSignature *) &put_path[putlen]
1965  : NULL;
1966  const char *data
1967  = has_path
1968  ? (const char *) &last_sig[1]
1969  : (const char *) &put_path[putlen];
1970  size_t var_meta_size
1971  = putlen * sizeof(struct GNUNET_DHT_PathElement)
1972  + (has_path ? sizeof (*last_sig) : 0)
1973  + (truncated ? sizeof (*trunc_peer) : 0);
1974  struct GNUNET_DATACACHE_Block bd = {
1975  .key = put->key,
1976  .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
1977  .type = ntohl (put->type),
1978  .ro = ro,
1979  .data_size = msize - sizeof(*put) - var_meta_size,
1980  .data = data
1981  };
1982 
1983  if (NULL != trunc_peer)
1984  bd.trunc_peer = *trunc_peer;
1986  "PUT for `%s' from %s with RO (%s/%s)\n",
1987  GNUNET_h2s (&put->key),
1988  GNUNET_i2s (&peer->id),
1989  (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1990  has_path ? "R" : "-");
1992  {
1994  "# Expired PUTs discarded",
1995  1,
1996  GNUNET_NO);
1997  return;
1998  }
1999  if (GNUNET_NO ==
2001  bd.type,
2002  bd.data,
2003  bd.data_size))
2004  {
2005  GNUNET_break_op (0);
2006  return;
2007  }
2008  if (! has_path)
2009  putlen = 0;
2011  "# P2P PUT requests received",
2012  1,
2013  GNUNET_NO);
2015  "# P2P PUT bytes received",
2016  msize,
2017  GNUNET_NO);
2018  {
2019  struct GNUNET_HashCode test_key;
2021 
2023  bd.type,
2024  bd.data,
2025  bd.data_size,
2026  &test_key);
2027  switch (ret)
2028  {
2029  case GNUNET_YES:
2030  if (0 != GNUNET_memcmp (&test_key,
2031  &bd.key))
2032  {
2033  GNUNET_break_op (0);
2034  return;
2035  }
2036  break;
2037  case GNUNET_NO:
2038  /* cannot verify, good luck */
2039  break;
2040  case GNUNET_SYSERR:
2041  /* block type not supported, good luck */
2042  break;
2043  }
2044  }
2045 
2046  {
2047  struct GNUNET_CONTAINER_BloomFilter *bf;
2048  struct GNUNET_DHT_PathElement pp[putlen + 1];
2049 
2055  &peer->phash));
2056  /* extend 'put path' by sender */
2057  bd.put_path = pp;
2058  bd.put_path_length = putlen + 1;
2059  if (has_path)
2060  {
2061  unsigned int failure_offset;
2062 
2063  GNUNET_memcpy (pp,
2064  put_path,
2065  putlen * sizeof(struct GNUNET_DHT_PathElement));
2066  pp[putlen].pred = peer->id;
2067  pp[putlen].sig = *last_sig;
2068 #if SANITY_CHECKS
2069  /* TODO: might want to eventually implement probabilistic
2070  load-based path verification, but for now it is all or nothing */
2071  failure_offset
2073  bd.data_size,
2074  bd.expiration_time,
2075  trunc_peer,
2076  pp,
2077  putlen + 1,
2078  NULL, 0, /* get_path */
2079  &GDS_my_identity);
2080 #else
2081  failure_offset = 0;
2082 #endif
2083  if (0 != failure_offset)
2084  {
2085  GNUNET_break_op (0);
2087  "Recorded put path invalid at offset %u, truncating\n",
2088  failure_offset);
2089  GNUNET_assert (failure_offset <= putlen + 1);
2090  bd.put_path = &pp[failure_offset];
2091  bd.put_path_length = (putlen + 1) - failure_offset;
2093  bd.trunc_peer = pp[failure_offset - 1].pred;
2094  }
2095  }
2096  else
2097  {
2098  bd.put_path_length = 0;
2099  }
2100 
2101  /* give to local clients */
2103  &bd.key,
2104  0, NULL /* get path */));
2105 
2106  /* store locally */
2107  if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2108  (GDS_am_closest_peer (&put->key,
2109  bf)) )
2111  {
2112  enum GNUNET_GenericReturnValue forwarded;
2113 
2114  /* route to other peers */
2115  forwarded
2117  ntohs (put->desired_replication_level),
2118  ntohs (put->hop_count),
2119  bf);
2120  /* notify monitoring clients */
2121  bd.ro |= ((GNUNET_OK == forwarded)
2123  : 0);
2125  ntohs (put->hop_count),
2126  ntohs (put->desired_replication_level));
2127  }
2129  }
2130 }
2131 
2132 
2141 static void
2143  const struct GNUNET_HashCode *query_hash,
2144  struct GNUNET_BLOCK_Group *bg)
2145 {
2146  size_t block_size = 0;
2147 
2148  /* TODO: consider caching our HELLO block for a bit, to
2149  avoid signing too often here... */
2153  NULL,
2154  &block_size));
2155  {
2156  char block[block_size];
2157 
2158  if (GNUNET_OK !=
2161  block,
2162  &block_size))
2163  {
2165  "# FIND PEER requests ignored due to lack of HELLO",
2166  1,
2167  GNUNET_NO);
2168  }
2169  else if (GNUNET_BLOCK_REPLY_OK_MORE ==
2172  bg,
2174  NULL, 0,
2175  block,
2176  block_size))
2177  {
2178  struct GNUNET_DATACACHE_Block bd = {
2180  .expiration_time
2183  .key = GDS_my_identity_hash,
2184  .data = block,
2185  .data_size = block_size
2186  };
2187 
2189  &bd,
2190  query_hash,
2191  0, NULL /* get path */));
2192  }
2193  else
2194  {
2196  "# FIND PEER requests ignored due to Bloomfilter",
2197  1,
2198  GNUNET_NO);
2199  }
2200  }
2201 }
2202 
2203 
2212 static void
2214  const struct GNUNET_HashCode *query_hash,
2215  struct GNUNET_BLOCK_Group *bg)
2216 {
2217  /* Force non-random selection by hop count */
2218  struct PeerInfo *peer;
2219 
2220  peer = select_peer (query_hash,
2221  NULL,
2222  GDS_NSE_get () + 1);
2223  if ( (NULL != peer->hello) &&
2224  (! GNUNET_TIME_absolute_is_past (peer->hello_expiration)) &&
2229  bg,
2230  &peer->phash,
2231  NULL, 0, /* xquery */
2232  peer->hello,
2233  peer->hello_size)) )
2234  {
2235  struct GNUNET_DATACACHE_Block bd = {
2237  .expiration_time = peer->hello_expiration,
2238  .key = peer->phash,
2239  .data = peer->hello,
2240  .data_size = peer->hello_size
2241  };
2242 
2244  &bd,
2245  query_hash,
2246  0, NULL /* get path */));
2247  }
2248 }
2249 
2250 
2257 static void
2259  const struct GNUNET_DATACACHE_Block *bd)
2260 {
2261  struct PeerInfo *peer = cls;
2262 
2264  bd,
2265  &bd->key,
2266  0, NULL /* get path */));
2267 }
2268 
2269 
2277 static enum GNUNET_GenericReturnValue
2278 check_dht_p2p_get (void *cls,
2279  const struct PeerGetMessage *get)
2280 {
2281  uint16_t msize = ntohs (get->header.size);
2282  uint16_t result_filter_size = ntohs (get->result_filter_size);
2283 
2284  (void) cls;
2285  if (msize < sizeof(*get) + result_filter_size)
2286  {
2287  GNUNET_break_op (0);
2288  return GNUNET_SYSERR;
2289  }
2290  return GNUNET_OK;
2291 }
2292 
2293 
2300 static void
2302  const struct PeerGetMessage *get)
2303 {
2304  struct Target *t = cls;
2305  struct PeerInfo *peer = t->pi;
2306  uint16_t msize = ntohs (get->header.size);
2307  uint16_t result_filter_size = ntohs (get->result_filter_size);
2308  uint16_t hop_count = ntohs (get->hop_count);
2309  enum GNUNET_BLOCK_Type type = (enum GNUNET_BLOCK_Type) ntohl (get->type);
2311  get->options);
2313  const void *result_filter = (const void *) &get[1];
2314  const void *xquery = result_filter + result_filter_size;
2315  size_t xquery_size = msize - sizeof (*get) - result_filter_size;
2316 
2317  /* parse and validate message */
2319  "# P2P GET requests received",
2320  1,
2321  GNUNET_NO);
2323  "# P2P GET bytes received",
2324  msize,
2325  GNUNET_NO);
2326  if (GNUNET_NO ==
2328  type,
2329  &get->key,
2330  xquery,
2331  xquery_size))
2332  {
2333  /* request invalid */
2334  GNUNET_break_op (0);
2335  return;
2336  }
2337 
2338  {
2339  struct GNUNET_BLOCK_Group *bg;
2340  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2341 
2342  peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
2347  &peer->phash));
2349  type,
2350  result_filter,
2351  result_filter_size,
2352  "filter-size",
2353  result_filter_size,
2354  NULL);
2356  "GET for %s at %s after %u hops\n",
2357  GNUNET_h2s (&get->key),
2359  (unsigned int) hop_count);
2360  /* local lookup (this may update the bg) */
2362  (GDS_am_closest_peer (&get->key,
2363  peer_bf)) )
2364  {
2365  if ( (GNUNET_BLOCK_TYPE_DHT_HELLO == type) ||
2367  {
2369  "# P2P HELLO lookup requests processed",
2370  1,
2371  GNUNET_NO);
2373  &get->key,
2374  bg);
2377  &get->key,
2378  bg);
2379  }
2381  {
2383  eval = GDS_DATACACHE_get_closest (&get->key,
2384  type,
2385  xquery,
2386  xquery_size,
2387  bg,
2389  peer);
2390  else
2391  eval = GDS_DATACACHE_handle_get (&get->key,
2392  type,
2393  xquery,
2394  xquery_size,
2395  bg,
2397  peer);
2398  }
2399  }
2400  else
2401  {
2403  "# P2P GET requests ONLY routed",
2404  1,
2405  GNUNET_NO);
2406  }
2407 
2408  /* remember request for routing replies
2409  TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
2410  */
2411  GDS_ROUTING_add (&peer->id,
2412  type,
2413  bg, /* bg now owned by routing, but valid at least until end of this function! */
2414  options,
2415  &get->key,
2416  xquery,
2417  xquery_size);
2418 
2419  /* P2P forwarding */
2420  {
2421  bool forwarded = false;
2422  uint16_t desired_replication_level = ntohs (
2423  get->desired_replication_level);
2424 
2425  if (eval != GNUNET_BLOCK_REPLY_OK_LAST)
2426  forwarded = (GNUNET_OK ==
2428  options,
2429  desired_replication_level,
2430  hop_count,
2431  &get->key,
2432  xquery,
2433  xquery_size,
2434  bg,
2435  peer_bf));
2437  options
2438  | (forwarded
2439  ? 0
2441  type,
2442  hop_count,
2443  desired_replication_level,
2444  &get->key);
2445  }
2446  /* clean up; note that 'bg' is owned by routing now! */
2448  }
2449 }
2450 
2451 
2461 static bool
2463  const struct GNUNET_HashCode *query_hash,
2464  unsigned int get_path_length,
2465  const struct GNUNET_DHT_PathElement *get_path)
2466 {
2467  /* forward to local clients */
2469  "Forwarding reply to local clients\n");
2470  if (! GDS_CLIENTS_handle_reply (bd,
2471  query_hash,
2472  get_path_length,
2473  get_path))
2474  {
2475  GNUNET_break (0);
2476  return false;
2477  }
2479  get_path,
2480  get_path_length);
2481  if (GNUNET_YES == cache_results)
2482  {
2483  struct GNUNET_DHT_PathElement xput_path[GNUNET_NZL (get_path_length
2484  + bd->put_path_length)];
2485  struct GNUNET_DATACACHE_Block bdx = *bd;
2486 
2487  if (NULL != bd->put_path)
2488  GNUNET_memcpy (xput_path,
2489  bd->put_path,
2490  bd->put_path_length * sizeof(struct
2492  GNUNET_memcpy (&xput_path[bd->put_path_length],
2493  get_path,
2494  get_path_length * sizeof(struct GNUNET_DHT_PathElement));
2495  bdx.put_path = xput_path;
2496  bdx.put_path_length += get_path_length;
2497  GDS_DATACACHE_handle_put (&bdx);
2498  }
2499  /* forward to other peers */
2500  GDS_ROUTING_process (bd,
2501  query_hash,
2502  get_path_length,
2503  get_path);
2504  return true;
2505 }
2506 
2507 
2515 static enum GNUNET_GenericReturnValue
2516 check_dht_p2p_result (void *cls,
2517  const struct PeerResultMessage *prm)
2518 {
2519  uint16_t msize = ntohs (prm->header.size) - sizeof (*prm);
2521  = (enum GNUNET_DHT_RouteOption) ntohs (prm->options);
2522  bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
2523  bool tracked = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
2524 
2525  uint16_t get_path_length = ntohs (prm->get_path_length);
2526  uint16_t put_path_length = ntohs (prm->put_path_length);
2527  size_t vsize = (truncated ? sizeof (struct GNUNET_PeerIdentity) : 0)
2528  + (tracked ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) : 0);
2529 
2530  (void) cls;
2531  if ( (msize < vsize) ||
2532  (msize - vsize <
2533  (get_path_length + put_path_length)
2534  * sizeof(struct GNUNET_DHT_PathElement)) ||
2535  (get_path_length >
2536  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ||
2537  (put_path_length >
2538  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) )
2539  {
2540  GNUNET_break_op (0);
2541  return GNUNET_SYSERR;
2542  }
2543  return GNUNET_OK;
2544 }
2545 
2546 
2553 static void
2555  const struct PeerResultMessage *prm)
2556 {
2557  struct Target *t = cls;
2558  struct PeerInfo *peer = t->pi;
2559  uint16_t msize = ntohs (prm->header.size) - sizeof (*prm);
2560  enum GNUNET_DHT_RouteOption ro
2561  = (enum GNUNET_DHT_RouteOption) ntohs (prm->options);
2562  bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
2563  bool tracked = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
2564  uint16_t get_path_length = ntohs (prm->get_path_length);
2565  uint16_t put_path_length = ntohs (prm->put_path_length);
2566  const struct GNUNET_PeerIdentity *trunc_peer
2567  = truncated
2568  ? (const struct GNUNET_PeerIdentity *) &prm[1]
2569  : NULL;
2570  const struct GNUNET_DHT_PathElement *put_path
2571  = truncated
2572  ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
2573  : (const struct GNUNET_DHT_PathElement *) &prm[1];
2574  const struct GNUNET_DHT_PathElement *get_path
2575  = &put_path[put_path_length];
2576  const struct GNUNET_CRYPTO_EddsaSignature *last_sig
2577  = tracked
2578  ? (const struct GNUNET_CRYPTO_EddsaSignature *) &get_path[get_path_length]
2579  : NULL;
2580  const void *data
2581  = tracked
2582  ? (const void *) &last_sig[1]
2583  : (const void *) &get_path[get_path_length];
2584  size_t vsize = (truncated ? sizeof (struct GNUNET_PeerIdentity) : 0)
2585  + (tracked ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) : 0);
2586  struct GNUNET_DATACACHE_Block bd = {
2588  .put_path = put_path,
2589  .put_path_length = put_path_length,
2590  .key = prm->key,
2591  .type = ntohl (prm->type),
2592  .ro = ro,
2593  .data = data,
2594  .data_size = msize - vsize - (get_path_length + put_path_length)
2595  * sizeof(struct GNUNET_DHT_PathElement)
2596  };
2597 
2598  /* parse and validate message */
2600  {
2602  "# Expired results discarded",
2603  1,
2604  GNUNET_NO);
2605  return;
2606  }
2607  if (GNUNET_OK !=
2609  bd.type,
2610  bd.data,
2611  bd.data_size))
2612  {
2613  GNUNET_break_op (0);
2614  return;
2615  }
2617  "# P2P RESULTS received",
2618  1,
2619  GNUNET_NO);
2621  "# P2P RESULT bytes received",
2622  msize,
2623  GNUNET_NO);
2624  {
2626 
2628  bd.type,
2629  bd.data,
2630  bd.data_size,
2631  &bd.key);
2632  if (GNUNET_NO == ret)
2633  bd.key = prm->key;
2634  }
2635 
2636  /* if we got a HELLO, consider it for our own routing table */
2637  hello_check (&bd);
2638 
2639  /* Need to append 'peer' to 'get_path' */
2640  if (tracked)
2641  {
2642  struct GNUNET_DHT_PathElement xget_path[get_path_length + 1];
2643  struct GNUNET_DHT_PathElement *gp = xget_path;
2644  unsigned int failure_offset;
2645 
2646  GNUNET_memcpy (xget_path,
2647  get_path,
2648  get_path_length * sizeof(struct GNUNET_DHT_PathElement));
2649  xget_path[get_path_length].pred = peer->id;
2650  /* use memcpy(), as last_sig may not be aligned */
2651  memcpy (&xget_path[get_path_length].sig,
2652  last_sig,
2653  sizeof (*last_sig));
2654 #if SANITY_CHECKS
2655  /* TODO: might want to eventually implement probabilistic
2656  load-based path verification, but for now it is all or nothing */
2657  failure_offset
2659  bd.data_size,
2660  bd.expiration_time,
2661  trunc_peer,
2662  put_path,
2663  put_path_length,
2664  gp,
2665  get_path_length + 1,
2666  &GDS_my_identity);
2667 #else
2668  failure_offset = 0;
2669 #endif
2670  if (0 != failure_offset)
2671  {
2673  "Recorded path invalid at offset %u, truncating\n",
2674  failure_offset);
2675  GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length
2676  + 1);
2677  if (failure_offset < bd.put_path_length)
2678  {
2679  /* failure on put path */
2680  trunc_peer = &bd.put_path[failure_offset - 1].pred;
2682  bd.put_path = &bd.put_path[failure_offset];
2683  bd.put_path_length -= failure_offset;
2684  truncated = true;
2685  }
2686  else
2687  {
2688  /* failure on get path */
2689  failure_offset -= bd.put_path_length;
2690  if (0 == failure_offset)
2691  trunc_peer = &bd.put_path[bd.put_path_length - 1].pred;
2692  else
2693  trunc_peer = &gp[failure_offset - 1].pred;
2694  get_path_length -= failure_offset;
2695  gp = &gp[failure_offset];
2696  bd.put_path_length = 0;
2697  bd.put_path = NULL;
2699  truncated = true;
2700  }
2701  }
2703  "Extending GET path of length %u with %s\n",
2704  get_path_length,
2705  GNUNET_i2s (&peer->id));
2706  if (truncated)
2707  {
2708  GNUNET_assert (NULL != trunc_peer);
2709  bd.trunc_peer = *trunc_peer;
2710  }
2712  &prm->key,
2713  get_path_length + 1,
2714  gp));
2715  }
2716  else
2717  {
2718  if (truncated)
2719  {
2720  GNUNET_assert (NULL != trunc_peer);
2721  bd.trunc_peer = *trunc_peer;
2722  }
2724  &prm->key,
2725  0,
2726  NULL));
2727  }
2728 }
2729 
2730 
2738 static enum GNUNET_GenericReturnValue
2739 check_dht_p2p_hello (void *cls,
2740  const struct GNUNET_MessageHeader *hello)
2741 {
2742  struct Target *t = cls;
2743  struct PeerInfo *peer = t->pi;
2745  size_t hellob_size;
2746  void *hellob;
2748 
2750  &peer->id,
2751  &hellob,
2752  &hellob_size,
2753  &expiration);
2754  GNUNET_free (hellob);
2755  return ret;
2756 }
2757 
2758 
2765 static void
2767  const struct GNUNET_MessageHeader *hello)
2768 {
2769  struct Target *t = cls;
2770  struct PeerInfo *peer = t->pi;
2771 
2772  GNUNET_free (peer->hello);
2773  peer->hello_size = 0;
2776  &peer->id,
2777  &peer->hello,
2778  &peer->hello_size,
2779  &peer->hello_expiration));
2780 }
2781 
2782 
2783 void
2784 GDS_u_receive (void *cls,
2785  void **tctx,
2786  void **sctx,
2787  const void *message,
2788  size_t message_size)
2789 {
2790  struct Target *t = *tctx;
2791  struct GNUNET_MQ_MessageHandler core_handlers[] = {
2792  GNUNET_MQ_hd_var_size (dht_p2p_get,
2794  struct PeerGetMessage,
2795  t),
2796  GNUNET_MQ_hd_var_size (dht_p2p_put,
2798  struct PeerPutMessage,
2799  t),
2800  GNUNET_MQ_hd_var_size (dht_p2p_result,
2802  struct PeerResultMessage,
2803  t),
2804  GNUNET_MQ_hd_var_size (dht_p2p_hello,
2806  struct GNUNET_MessageHeader,
2807  t),
2809  };
2810  const struct GNUNET_MessageHeader *mh = message;
2811 
2812  (void) cls; /* the 'struct GDS_Underlay' */
2813  (void) sctx; /* our receiver address */
2814  if (NULL == t)
2815  {
2816  /* Received message claiming to originate from myself?
2817  Ignore! */
2818  GNUNET_break_op (0);
2819  return;
2820  }
2821  if (message_size < sizeof (*mh))
2822  {
2823  GNUNET_break_op (0);
2824  return;
2825  }
2826  if (message_size != ntohs (mh->size))
2827  {
2828  GNUNET_break_op (0);
2829  return;
2830  }
2832  "Handling message of type %u from peer %s\n",
2833  ntohs (mh->type),
2834  GNUNET_i2s (&t->pi->id));
2835  if (GNUNET_OK !=
2836  GNUNET_MQ_handle_message (core_handlers,
2837  mh))
2838  {
2839  GNUNET_break_op (0);
2840  return;
2841  }
2842 }
2843 
2844 
2852 void
2853 GDS_try_connect (void *cls,
2854  const char *uri)
2855 {
2856  const struct GNUNET_PeerIdentity *pid = cls;
2857  struct GNUNET_HashCode phash;
2858  int peer_bucket;
2859  struct PeerBucket *bucket;
2860 
2861  if (0 == GNUNET_memcmp (&GDS_my_identity,
2862  pid))
2863  {
2865  "Got a HELLO for my own PID, ignoring it\n");
2866  return; /* that's us! */
2867  }
2869  sizeof(*pid),
2870  &phash);
2871  peer_bucket = find_bucket (&phash);
2872  GNUNET_assert ( (peer_bucket >= 0) &&
2873  ((unsigned int) peer_bucket < MAX_BUCKETS));
2874  bucket = &k_buckets[peer_bucket];
2875  for (struct PeerInfo *pi = bucket->head;
2876  NULL != pi;
2877  pi = pi->next)
2878  if (0 ==
2879  GNUNET_memcmp (&pi->id,
2880  pid))
2881  {
2882  /* already connected */
2884  uri);
2885  return;
2886  }
2887  if (bucket->peers_size >= bucket_size)
2888  return; /* do not care */
2890  "Discovered peer %s at %s suitable for bucket %d (%u/%u), trying to connect\n",
2891  GNUNET_i2s (pid),
2892  uri,
2893  peer_bucket,
2894  bucket->peers_size,
2895  bucket_size);
2896  /* new peer that we like! */
2898  uri);
2899 }
2900 
2901 
2907 void
2909 {
2910  for (unsigned int bc = 0; bc<closest_bucket; bc++)
2911  {
2912  struct PeerBucket *bucket = &k_buckets[bc];
2913  unsigned int count = 0;
2914 
2915  for (struct PeerInfo *pos = bucket->head;
2916  NULL != pos;
2917  pos = pos->next)
2918  {
2919  if (count >= bucket_size)
2920  break; /* we only consider first #bucket_size entries per bucket */
2921  count++;
2922  do_send (pos,
2923  msg);
2924  }
2925  }
2926 }
2927 
2928 
2931 {
2932 
2933  unsigned long long temp_config_num;
2934 
2937  "DHT",
2938  "DISABLE_TRY_CONNECT");
2939  if (GNUNET_OK ==
2941  "DHT",
2942  "bucket_size",
2943  &temp_config_num))
2944  bucket_size = (unsigned int) temp_config_num;
2947  "DHT",
2948  "CACHE_RESULTS");
2950  GNUNET_YES);
2951  return GNUNET_OK;
2952 }
2953 
2954 
2955 void
2957 {
2958  if (NULL == all_connected_peers)
2959  return;
2960  GNUNET_assert (0 ==
2963  all_connected_peers = NULL;
2964  GNUNET_assert (NULL == find_peer_task);
2965 }
2966 
2967 
2968 struct GNUNET_PeerIdentity *
2970 {
2971  return &GDS_my_identity;
2972 }
2973 
2974 
2975 /* end of gnunet-service-dht_neighbours.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
@ GNUNET_BLOCK_TYPE_DHT_HELLO
Type of a block that contains a DHT-NG HELLO for a peer.
#define GNUNET_SIGNATURE_PURPOSE_DHT_HOP
Signature by which a peer affirms that it forwarded a message in the DHT.
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static struct PendingResolutions * head
Head of list of pending resolution requests.
Definition: gnunet-ats.c:230
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
struct GNUNET_HashCode key
The key used in the DHT.
static int get
Get DID Documement for DID Flag.
Definition: gnunet-did.c:66
uint32_t data
The data value.
static char * value
Value of the record to add/remove.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
struct GNUNET_PeerIdentity GDS_my_identity
Identity of this peer.
double GDS_NSE_get(void)
Return the current NSE.
struct GNUNET_DHTU_PreferenceHandle * GDS_u_hold(struct GDS_Underlay *u, struct GNUNET_DHTU_Target *target)
Create a hold on target at underlay u.
struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key
Our private key.
void GDS_u_send(struct GDS_Underlay *u, struct GNUNET_DHTU_Target *target, const void *msg, size_t msg_size, GNUNET_SCHEDULER_TaskCallback finished_cb, void *finished_cb_cls)
Send message to some other participant over the network.
struct GNUNET_HELLO_Builder * GDS_my_hello
Our HELLO.
void GDS_u_drop(struct GDS_Underlay *u, struct GNUNET_DHTU_PreferenceHandle *ph)
Drop a hold ph from underlay u.
void GDS_u_try_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Ask all underlays to connect to peer pid at address.
struct GNUNET_HashCode GDS_my_identity_hash
Hash of the identity of this peer.
GNUnet DHT globals.
void GDS_CLIENTS_process_get(enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, const struct GNUNET_HashCode *key)
Check if some client is monitoring GET messages and notify them in that case.
void GDS_CLIENTS_process_get_resp(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length)
Check if some client is monitoring GET RESP messages and notify them in that case.
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
struct GNUNET_BLOCK_Context * GDS_block_context
Our handle to the BLOCK library.
void GDS_CLIENTS_process_put(const struct GNUNET_DATACACHE_Block *bd, uint32_t hop_count, uint32_t desired_replication_level)
Check if some client is monitoring PUT messages and notify them in that case.
bool GDS_CLIENTS_handle_reply(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply we've received from another peer.
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
Configuration we use.
enum GNUNET_BLOCK_ReplyEvaluationResult GDS_DATACACHE_get_closest(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback cb, void *cb_cls)
Handle a request for data close to a key that we have received from another peer.
enum GNUNET_BLOCK_ReplyEvaluationResult GDS_DATACACHE_handle_get(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback gc, void *gc_cls)
Handle a GET request we've received from another peer.
void GDS_DATACACHE_handle_put(const struct GNUNET_DATACACHE_Block *bd)
Handle a datum we've received from another peer.
static void send_find_peer_message(void *cls)
Task to send a find peer message for our own peer identifier so that we can find the closest peers in...
bool GDS_NEIGHBOURS_handle_reply(struct PeerInfo *pi, const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply (route to origin).
static void handle_dht_p2p_result(void *cls, const struct PeerResultMessage *prm)
Core handler for p2p result messages.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_put(const struct GNUNET_DATACACHE_Block *bd, uint16_t desired_replication_level, uint16_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf)
Perform a PUT operation.
#define MAXIMUM_PENDING_PER_PEER
Maximum allowed number of pending messages per peer.
static int disable_try_connect
Option for testing that disables the 'connect' function of the DHT.
static unsigned int newly_found_peers
How many peers have we added since we sent out our last find peer request?
static void send_done_cb(void *cls)
Function called whenever we finished sending to a target.
#define DEFAULT_BUCKET_SIZE
What is the maximum number of peers in a given bucket.
void GDS_NEIGHBOURS_done()
Shutdown neighbours subsystem.
void GDS_u_disconnect(void *ctx)
Function to call when we disconnected from a peer and can henceforth cannot transmit to that peer any...
static void handle_dht_p2p_hello(void *cls, const struct GNUNET_MessageHeader *hello)
Core handler for p2p HELLO messages.
static void handle_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Core handler for p2p get requests.
void GDS_NEIGHBOURS_broadcast(const struct GNUNET_MessageHeader *msg)
Send msg to all peers in our buckets.
#define FIND_PEER_REPLICATION_LEVEL
Desired replication level for FIND PEER requests.
static void handle_find_local_hello(struct PeerInfo *pi, const struct GNUNET_HashCode *query_hash, struct GNUNET_BLOCK_Group *bg)
We have received a request for nearby HELLOs.
static unsigned int get_forward_count(uint16_t hop_count, uint16_t target_replication)
To how many peers should we (on average) forward the request to obtain the desired target_replication...
static void do_send(struct PeerInfo *pi, const struct GNUNET_MessageHeader *msg)
Send msg to pi.
static struct PeerInfo * select_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops)
Select a peer from the routing table that would be a good routing destination for sending a message f...
static int find_bucket(const struct GNUNET_HashCode *hc)
Find the optimal bucket for this key.
static enum GNUNET_GenericReturnValue check_dht_p2p_put(void *cls, const struct PeerPutMessage *put)
Check validity of a p2p put request.
static struct GNUNET_CONTAINER_MultiPeerMap * all_connected_peers
Hash map of all CORE-connected peers, for easy removal from k_buckets on disconnect.
static void handle_local_result(void *cls, const struct GNUNET_DATACACHE_Block *bd)
Handle an exact result from local datacache for a GET operation.
struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id()
Get the ID of the local node.
#define DHT_MINIMUM_FIND_PEER_INTERVAL
How long at least to wait before sending another find peer request.
void GDS_try_connect(void *cls, const char *uri)
Callback function used to extract URIs from a builder.
static int cache_results
Do we cache all results that we are routing in the local datacache?
void GDS_u_connect(void *cls, struct GNUNET_DHTU_Target *target, const struct GNUNET_PeerIdentity *pid, void **ctx)
Function to call when we connect to a peer and can henceforth transmit to that peer.
static enum GNUNET_GenericReturnValue check_dht_p2p_result(void *cls, const struct PeerResultMessage *prm)
Check validity of p2p result message.
static struct GNUNET_SCHEDULER_Task * find_peer_task
Task that sends FIND PEER requests.
static bool process_reply_with_path(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Process a reply, after the get_path has been updated.
#define MAX_BUCKETS
How many buckets will we allow in total.
static enum GNUNET_GenericReturnValue check_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Check validity of p2p get request.
static enum GNUNET_GenericReturnValue check_dht_p2p_hello(void *cls, const struct GNUNET_MessageHeader *hello)
Check validity of a p2p hello message.
static unsigned int get_target_peers(const struct GNUNET_HashCode *key, struct GNUNET_CONTAINER_BloomFilter *bloom, uint16_t hop_count, uint16_t target_replication, struct PeerInfo ***targets)
Compute the set of peers that the given request should be forwarded to.
static void hello_check(const struct GNUNET_DATACACHE_Block *bd)
If we got a HELLO, consider it for our own routing table.
static enum GNUNET_GenericReturnValue add_known_to_bloom(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Add each of the peers we already know to the Bloom filter of the request so that we don't get duplica...
static unsigned int bucket_size
Maximum size for each bucket.
static void handle_find_my_hello(struct PeerInfo *pi, const struct GNUNET_HashCode *query_hash, struct GNUNET_BLOCK_Group *bg)
We have received a request for a HELLO.
enum GNUNET_GenericReturnValue GDS_am_closest_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom)
Check whether my identity is closer than any known peers.
static unsigned int closest_bucket
The lowest currently used bucket, initially 0 (for 0-bits matching bucket).
static void sign_path(const void *data, size_t data_size, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *pred, const struct GNUNET_PeerIdentity *succ, struct GNUNET_CRYPTO_EddsaSignature *sig)
Sign that we are routing a message from pred to succ.
static struct PeerBucket k_buckets[sizeof(struct GNUNET_HashCode) *8]
The buckets.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_init()
Initialize neighbours subsystem.
static void update_hold(struct PeerBucket *bucket)
The list of the first bucket_size peers of bucket changed.
void GDS_u_receive(void *cls, void **tctx, void **sctx, const void *message, size_t message_size)
Function to call when we receive a message.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_get(enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint16_t desired_replication_level, uint16_t hop_count, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, struct GNUNET_CONTAINER_BloomFilter *peer_bf)
Perform a GET operation.
struct PeerInfo * GDS_NEIGHBOURS_lookup_peer(const struct GNUNET_PeerIdentity *target)
Lookup peer by peer's identity.
static void handle_dht_p2p_put(void *cls, const struct PeerPutMessage *put)
Core handler for p2p put requests.
#define DHT_AVG_FIND_PEER_INTERVAL
How long to additionally wait on average per bucket_size to send out the FIND PEER requests if we did...
GNUnet DHT routing code.
void GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *bg, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size)
Add a new entry to our routing table.
void GDS_ROUTING_process(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply (route to origin).
GNUnet DHT tracking of requests for routing replies.
static char buf[2048]
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
static struct GNUNET_SCHEDULER_Task * t
Main task.
Helper library for handling HELLOs.
Helper library for handling HELLO URIs.
Constants for network protocols.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_set_seen(struct GNUNET_BLOCK_Group *bg, const struct GNUNET_HashCode *seen_results, unsigned int seen_results_count)
Update block group to filter out the given results.
Definition: block.c:363
enum GNUNET_BLOCK_ReplyEvaluationResult GNUNET_BLOCK_check_reply(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *group, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size)
Function called to validate if a reply is good for a particular query.
Definition: block.c:337
enum GNUNET_GenericReturnValue GNUNET_BLOCK_check_block(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size)
Function called to validate a block.
Definition: block.c:319
enum GNUNET_GenericReturnValue GNUNET_BLOCK_check_query(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size)
Function called to validate a request.
Definition: block.c:296
GNUNET_BLOCK_ReplyEvaluationResult
Possible ways for how a block may relate to a query.
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition: block.c:192
struct GNUNET_BLOCK_Group * GNUNET_BLOCK_group_create(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *raw_data, size_t raw_data_size,...)
Create a new block group.
Definition: block.c:247
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_serialize(struct GNUNET_BLOCK_Group *bg, void **raw_data, size_t *raw_data_size)
Serialize state of a block group.
Definition: block.c:175
enum GNUNET_GenericReturnValue GNUNET_BLOCK_get_key(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key)
Function called to obtain the key for a block.
Definition: block.c:276
@ GNUNET_BLOCK_REPLY_OK_MORE
Valid result, and there may be more.
@ GNUNET_BLOCK_REPLY_OK_LAST
Last possible valid result.
int GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this Bloom filter into the given data array.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
bool GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_CONSTANTS_BLOOMFILTER_K
K-value that must be used for the bloom filters in 'GET' queries.
#define GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
What is the maximum size for encrypted messages? Note that this number imposes a clear limit on the m...
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
GNUNET_DHT_RouteOption
Options for routing.
#define GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL
Maximum allowed replication level for all requests.
unsigned int GNUNET_DHT_verify_path(const void *data, size_t data_size, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *bpid, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_len, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_len, const struct GNUNET_PeerIdentity *me)
Verify signatures on a path consisting of put_path and get_path in reverse order (starting at the las...
Definition: dht_api.c:1353
@ GNUNET_DHT_RO_TRUNCATED
Flag set if the path was truncated.
@ GNUNET_DHT_RO_RECORD_ROUTE
We should keep track of the route that the message took in the P2P network.
@ GNUNET_DHT_RO_LAST_HOP
Flag given to monitors if this was the last hop for a GET/PUT.
@ GNUNET_DHT_RO_FIND_APPROXIMATE
Approximate results are fine.
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CRYPTO_hash_xor(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result)
compute result = a ^ b
Definition: crypto_hash.c:135
int GNUNET_CRYPTO_hash_xorcmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2, const struct GNUNET_HashCode *target)
Find out which of the two GNUNET_CRYPTO_hash codes is closer to target in the XOR metric (Kademlia).
Definition: crypto_hash.c:242
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
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_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
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.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_block(const void *block, size_t block_size)
Parse block into builder.
Definition: hello-uri.c:360
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition: hello-uri.c:319
enum GNUNET_GenericReturnValue GNUNET_HELLO_dht_msg_to_block(const struct GNUNET_MessageHeader *hello, const struct GNUNET_PeerIdentity *pid, void **block, size_t *block_size, struct GNUNET_TIME_Absolute *block_expiration)
Convert a DHT hello message to a HELLO block.
Definition: hello-uri.c:844
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, struct GNUNET_PeerIdentity *pid, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition: hello-uri.c:822
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_to_block(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, void *block, size_t *block_size)
Generate DHT block from a builder.
Definition: hello-uri.c:699
unsigned int GNUNET_CRYPTO_hash_count_leading_zeros(const struct GNUNET_HashCode *h)
Count the number of leading 0 bits in h.
Definition: crypto_hash.c:176
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_B2S(obj)
Convert a fixed-sized object to a string using GNUNET_b2s().
#define GNUNET_MAX(a, b)
#define GNUNET_NZL(l)
Macro used to avoid using 0 for the length of a variable-size array (Non-Zero-Length).
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
int GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition: mq.c:205
#define GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
HELLO advertising a neighbours addresses.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
Data is returned to peer from DHT.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_GET
Peer tries to find data in DHT.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
Peer is storing data in DHT.
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:1268
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:944
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:1241
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_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:484
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition: time.c:669
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
Information we keep per underlay.
Block group data.
Internal representation of the hash map.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
an ECC signature using EdDSA.
Information about a block stored in the datacache.
const struct GNUNET_DHT_PathElement * put_path
PUT path taken by the block, array of peer identities.
enum GNUNET_BLOCK_Type type
Type of the block.
const void * data
Actual block data.
enum GNUNET_DHT_RouteOption ro
Options for routing for the block.
struct GNUNET_PeerIdentity trunc_peer
If the path was truncated, this is the peer ID at which the path was truncated.
struct GNUNET_HashCode key
Key of the block.
size_t data_size
Number of bytes in data.
unsigned int put_path_length
Length of the put_path array.
struct GNUNET_TIME_Absolute expiration_time
When does the block expire?
Opaque handle expressing a preference of the DHT to keep a particular target connected.
Opaque handle that the underlay offers for the target peer when sending messages to another peer.
Message signed by a peer when doing path tracking.
struct GNUNET_HashCode h_data
Hash over the payload of the block.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Must be GNUNET_SIGNATURE_PURPOSE_DHT_HOP.
struct GNUNET_PeerIdentity pred
Previous hop the message was received from.
struct GNUNET_PeerIdentity succ
Next hop the message was forwarded to.
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
struct GNUNET_PeerIdentity pred
Previous peer on the path (matches "pred" in the signed field).
struct GNUNET_CRYPTO_EddsaSignature sig
Signature affirming the hop of type GNUNET_SIGNATURE_PURPOSE_DHT_HOP.
Context for building (or parsing) HELLO URIs.
Definition: hello-uri.c:184
A 512-bit hashcode.
uint32_t bits[512/8/sizeof(uint32_t)]
Message handler for a specific message type.
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:136
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition: scheduler.c:140
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Peers are grouped into buckets.
struct PeerInfo * head
Head of DLL.
struct PeerInfo * tail
Tail of DLL.
unsigned int peers_size
Number of peers in the bucket.
uint16_t result_filter_size
Size of the result filter.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_GET.
uint16_t hop_count
Hop count.
uint16_t desired_replication_level
Desired replication level for this request.
uint16_t options
Processing options.
struct GNUNET_HashCode key
The key we are looking for.
uint32_t type
Desired content type.
Entry for a peer in a bucket.
struct GNUNET_TIME_Absolute hello_expiration
When does our HELLO from this peer expire?
size_t hello_size
Number of bytes in hello.
struct PeerInfo * next
Next peer entry (DLL)
struct GNUNET_PeerIdentity id
What is the identity of the peer?
struct Target * t_tail
Tail of DLL of targets for this peer.
struct PeerInfo * prev
Prev peer entry (DLL)
struct GNUNET_HashCode phash
Hash of id.
int peer_bucket
Which bucket is this peer in?
struct Target * t_head
Head of DLL of targets for this peer.
void * hello
Block with a HELLO of this peer.
uint16_t desired_replication_level
Replication level for this message.
uint16_t hop_count
Hop count.
uint32_t type
Content type, must not be zero.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT.
struct GNUNET_HashCode key
The key we are storing under.
uint16_t options
Processing options.
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
uint16_t put_path_length
Length of the PUT path that follows (if tracked).
uint16_t get_path_length
Length of the GET path that follows (if tracked).
uint16_t options
Message options, actually an 'enum GNUNET_DHT_RouteOption' value in NBO.
struct GNUNET_HashCode key
The key of the corresponding GET request.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT.
uint16_t put_path_length
Length of the PUT path that follows (if tracked).
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
struct PendingResolutions * next
Kept in a DLL.
Definition: gnunet-ats.c:159
List of targets that we can use to reach this peer.
struct Target * prev
Kept in a DLL.
struct PeerInfo * pi
Peer this is a target for.
struct Target * next
Kept in a DLL.
unsigned int load
Set to number of messages are waiting for the transmission to finish.
struct GNUNET_DHTU_PreferenceHandle * ph
Handle used to 'hold' the connection to this peer.
struct GDS_Underlay * u
Underlay providing this target.
struct GNUNET_DHTU_Target * utarget
Handle for sending messages to this peer.
bool dropped
Set to true if the target was dropped, but we could not clean up yet because busy was also true.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.