GNUnet  0.10.x
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 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_nse_service.h"
34 #include "gnunet_ats_service.h"
35 #include "gnunet_core_service.h"
36 #include "gnunet_datacache_lib.h"
38 #include "gnunet_hello_lib.h"
39 #include "gnunet_dht_service.h"
41 #include "gnunet-service-dht.h"
45 #include "gnunet-service-dht_nse.h"
47 #include "dht.h"
48 
49 #define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__)
50 
54 #define SANITY_CHECKS 1
55 
59 #define MAX_BUCKETS sizeof (struct GNUNET_HashCode) * 8
60 
64 #define DEFAULT_BUCKET_SIZE 8
65 
69 #define FIND_PEER_REPLICATION_LEVEL 4
70 
74 #define MAXIMUM_REPLICATION_LEVEL 16
75 
79 #define MAXIMUM_PENDING_PER_PEER 64
80 
84 #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
85 
89 #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
90 
94 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
95 
100 
101 
103 
108 {
113 
118 
122  uint32_t type GNUNET_PACKED;
123 
128 
133 
138 
143 
148 
153 
154  /* put path (if tracked) */
155 
156  /* Payload */
157 
158 };
159 
160 
165 {
170 
174  uint32_t type GNUNET_PACKED;
175 
180 
184  uint32_t get_path_length GNUNET_PACKED;
185 
190 
194  struct GNUNET_HashCode key;
195 
196  /* put path (if tracked) */
197 
198  /* get path (if tracked) */
199 
200  /* Payload */
201 
202 };
203 
204 
209 {
214 
219 
223  uint32_t type GNUNET_PACKED;
224 
229 
234 
238  uint32_t xquery_size;
239 
243  uint32_t bf_mutator;
244 
249 
253  struct GNUNET_HashCode key;
254 
255  /* xquery */
256 
257  /* result bloomfilter */
258 
259 };
261 
262 
266 struct PeerInfo
267 {
271  struct PeerInfo *next;
272 
276  struct PeerInfo *prev;
277 
282 
286  const struct GNUNET_PeerIdentity *id;
287 
291  struct GNUNET_HashCode phash;
292 
297 
298 };
299 
300 
305 {
309  struct PeerInfo *head;
310 
314  struct PeerInfo *tail;
315 
319  unsigned int peers_size;
320 };
321 
322 
327 {
328 
333 
338 
342  uint32_t strength;
343 };
344 
345 
349 static int cache_results;
350 
355 
359 static unsigned int closest_bucket;
360 
365 static unsigned int newly_found_peers;
366 
371 
376 
382 
388 
392 static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
393 
398 
403 
408 
413 
418 
419 
427 static int
428 find_bucket (const struct GNUNET_HashCode *hc)
429 {
430  unsigned int bits;
431 
433  if (bits == MAX_BUCKETS)
434  {
435  /* How can all bits match? Got my own ID? */
436  GNUNET_break (0);
437  return GNUNET_SYSERR;
438  }
439  return MAX_BUCKETS - bits - 1;
440 }
441 
442 
449 static void
450 offer_hello_done (void *cls)
451 {
452  struct ConnectInfo *ci = cls;
453 
454  ci->oh = NULL;
455 }
456 
457 
466 static int
467 free_connect_info (void *cls,
468  const struct GNUNET_PeerIdentity *peer,
469  void *value)
470 {
471  struct ConnectInfo *ci = value;
472 
473  (void) cls;
475  GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
476  peer,
477  ci));
478  if (NULL != ci->sh)
479  {
481  ci->sh = NULL;
482  }
483  if (NULL != ci->oh)
484  {
486  ci->oh = NULL;
487  }
488  GNUNET_free (ci);
489  return GNUNET_YES;
490 }
491 
492 
501 static void
503  const struct GNUNET_MessageHeader *h)
504 {
505  int bucket;
506  struct GNUNET_HashCode pid_hash;
507  struct ConnectInfo *ci;
508  uint32_t strength;
509 
510  GNUNET_CRYPTO_hash (pid,
511  sizeof (struct GNUNET_PeerIdentity),
512  &pid_hash);
513  bucket = find_bucket (&pid_hash);
514  if (bucket < 0)
515  return; /* self? */
516  ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
517  pid);
518 
519  if (k_buckets[bucket].peers_size < bucket_size)
520  strength = (bucket_size - k_buckets[bucket].peers_size) * bucket;
521  else
522  strength = bucket; /* minimum value of connectivity */
523  if (GNUNET_YES ==
524  GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
525  pid))
526  strength *= 2; /* double for connected peers */
527  else if (k_buckets[bucket].peers_size > bucket_size)
528  strength = 0; /* bucket full, we really do not care about more */
529 
530  if ( (0 == strength) &&
531  (NULL != ci) )
532  {
533  /* release request */
535  free_connect_info (NULL,
536  pid,
537  ci));
538  return;
539  }
540  if (NULL == ci)
541  {
542  ci = GNUNET_new (struct ConnectInfo);
544  GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
545  pid,
546  ci,
548  }
549  if ( (NULL != ci->oh) &&
550  (NULL != h) )
552  if (NULL != h)
554  h,
556  ci);
557  if ( (NULL != ci->sh) &&
558  (ci->strength != strength) )
560  if (ci->strength != strength)
561  ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch,
562  pid,
563  strength);
564  ci->strength = strength;
565 }
566 
567 
580 static int
582  const struct GNUNET_PeerIdentity *pid,
583  void *value)
584 {
585  (void) cls;
586  (void) value;
587  try_connect (pid,
588  NULL);
589  return GNUNET_YES;
590 }
591 
592 
599 static void
601 {
602  GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
604  NULL);
605 }
606 
607 
617 static int
619  const struct GNUNET_PeerIdentity *key,
620  void *value)
621 {
622  struct GNUNET_BLOCK_Group *bg = cls;
623  struct GNUNET_HashCode key_hash;
624 
625  (void) cls;
626  (void) value;
627  GNUNET_CRYPTO_hash (key,
628  sizeof (struct GNUNET_PeerIdentity),
629  &key_hash);
631  &key_hash,
632  1);
634  "Adding known peer (%s) to bloomfilter for FIND PEER\n",
635  GNUNET_i2s (key));
636  return GNUNET_YES;
637 }
638 
639 
647 static void
649 {
650  struct GNUNET_TIME_Relative next_send_time;
651  struct GNUNET_BLOCK_Group *bg;
652  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
653 
654  (void) cls;
655  find_peer_task = NULL;
657  {
658  /* If we are finding many peers already, no need to send out our request right now! */
659  find_peer_task =
662  NULL);
663  newly_found_peers = 0;
664  return;
665  }
669  UINT32_MAX),
670  NULL,
671  0,
672  "filter-size",
674  NULL);
675  GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers,
677  bg);
679  gettext_noop ("# FIND PEER messages initiated"),
680  1,
681  GNUNET_NO);
682  peer_bf
686  // FIXME: pass priority!?
690  0,
692  NULL,
693  0,
694  bg,
695  peer_bf);
698  /* schedule next round */
699  next_send_time.rel_value_us =
700  DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us +
702  DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us /
703  (newly_found_peers + 1));
704  newly_found_peers = 0;
705  GNUNET_assert (NULL == find_peer_task);
706  find_peer_task =
707  GNUNET_SCHEDULER_add_delayed (next_send_time,
709  NULL);
710 }
711 
712 
721 static void *
723  const struct GNUNET_PeerIdentity *peer,
724  struct GNUNET_MQ_Handle *mq)
725 {
726  struct PeerInfo *pi;
727 
728  (void) cls;
729  /* Check for connect to self message */
730  if (0 == GNUNET_memcmp (&my_identity,
731  peer))
732  return NULL;
734  "Connected to %s\n",
735  GNUNET_i2s (peer));
737  GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
738  peer));
740  gettext_noop ("# peers connected"),
741  1,
742  GNUNET_NO);
743  pi = GNUNET_new (struct PeerInfo);
744  pi->id = peer;
745  pi->mq = mq;
746  GNUNET_CRYPTO_hash (peer,
747  sizeof (struct GNUNET_PeerIdentity),
748  &pi->phash);
749  pi->peer_bucket = find_bucket (&pi->phash);
750  GNUNET_assert ( (pi->peer_bucket >= 0) &&
751  ((unsigned int) pi->peer_bucket < MAX_BUCKETS) );
754  pi);
757  (unsigned int) pi->peer_bucket);
759  GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
760  pi->id,
761  pi,
763  if ( (pi->peer_bucket > 0) &&
765  {
768  }
769  if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
771  {
772  /* got a first connection, good time to start with FIND PEER requests... */
773  GNUNET_assert (NULL == find_peer_task);
775  NULL);
776  }
777  return pi;
778 }
779 
780 
788 static void
790  const struct GNUNET_PeerIdentity *peer,
791  void *internal_cls)
792 {
793  struct PeerInfo *to_remove = internal_cls;
794 
795  (void) cls;
796  /* Check for disconnect from self message */
797  if (NULL == to_remove)
798  return;
800  "Disconnected %s\n",
801  GNUNET_i2s (peer));
803  gettext_noop ("# peers connected"),
804  -1,
805  GNUNET_NO);
807  GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
808  peer,
809  to_remove));
810  if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
812  {
813  GNUNET_SCHEDULER_cancel (find_peer_task);
814  find_peer_task = NULL;
815  }
816  GNUNET_assert (to_remove->peer_bucket >= 0);
818  k_buckets[to_remove->peer_bucket].tail,
819  to_remove);
820  GNUNET_assert (k_buckets[to_remove->peer_bucket].peers_size > 0);
821  k_buckets[to_remove->peer_bucket].peers_size--;
822  while ( (closest_bucket > 0) &&
823  (0 == k_buckets[to_remove->peer_bucket].peers_size) )
824  closest_bucket--;
825  if (k_buckets[to_remove->peer_bucket].peers_size < bucket_size)
827  GNUNET_free (to_remove);
828 }
829 
830 
839 static unsigned int
841  uint32_t target_replication)
842 {
843  uint32_t random_value;
844  uint32_t forward_count;
845  float target_value;
846 
847  if (hop_count > GDS_NSE_get () * 4.0)
848  {
849  /* forcefully terminate */
851  gettext_noop ("# requests TTL-dropped"),
852  1, GNUNET_NO);
853  return 0;
854  }
855  if (hop_count > GDS_NSE_get () * 2.0)
856  {
857  /* Once we have reached our ideal number of hops, only forward to 1 peer */
858  return 1;
859  }
860  /* bound by system-wide maximum */
861  target_replication =
862  GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL, target_replication);
863  target_value =
864  1 + (target_replication - 1.0) / (GDS_NSE_get () +
865  ((float) (target_replication - 1.0) *
866  hop_count));
867  /* Set forward count to floor of target_value */
868  forward_count = (uint32_t) target_value;
869  /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
870  target_value = target_value - forward_count;
871  random_value =
873  if (random_value < (target_value * UINT32_MAX))
874  forward_count++;
875  return forward_count;
876 }
877 
878 
890 static unsigned int
891 get_distance (const struct GNUNET_HashCode *target,
892  const struct GNUNET_HashCode *have)
893 {
894  unsigned int bucket;
895  unsigned int msb;
896  unsigned int lsb;
897  unsigned int i;
898 
899  /* We have to represent the distance between two 2^9 (=512)-bit
900  * numbers as a 2^5 (=32)-bit number with "0" being used for the
901  * two numbers being identical; furthermore, we need to
902  * guarantee that a difference in the number of matching
903  * bits is always represented in the result.
904  *
905  * We use 2^32/2^9 numerical values to distinguish between
906  * hash codes that have the same LSB bit distance and
907  * use the highest 2^9 bits of the result to signify the
908  * number of (mis)matching LSB bits; if we have 0 matching
909  * and hence 512 mismatching LSB bits we return -1 (since
910  * 512 itself cannot be represented with 9 bits) */
911 
912  /* first, calculate the most significant 9 bits of our
913  * result, aka the number of LSBs */
914  bucket = GNUNET_CRYPTO_hash_matching_bits (target,
915  have);
916  /* bucket is now a value between 0 and 512 */
917  if (bucket == 512)
918  return 0; /* perfect match */
919  if (bucket == 0)
920  return (unsigned int) -1; /* LSB differs; use max (if we did the bit-shifting
921  * below, we'd end up with max+1 (overflow)) */
922 
923  /* calculate the most significant bits of the final result */
924  msb = (512 - bucket) << (32 - 9);
925  /* calculate the 32-9 least significant bits of the final result by
926  * looking at the differences in the 32-9 bits following the
927  * mismatching bit at 'bucket' */
928  lsb = 0;
929  for (i = bucket + 1;
930  (i < sizeof (struct GNUNET_HashCode) * 8) && (i < bucket + 1 + 32 - 9); i++)
931  {
932  if (GNUNET_CRYPTO_hash_get_bit (target, i) !=
933  GNUNET_CRYPTO_hash_get_bit (have, i))
934  lsb |= (1 << (bucket + 32 - 9 - i)); /* first bit set will be 10,
935  * last bit set will be 31 -- if
936  * i does not reach 512 first... */
937  }
938  return msb | lsb;
939 }
940 
941 
952 int
954  const struct GNUNET_CONTAINER_BloomFilter *bloom)
955 {
956  int bits;
957  int other_bits;
958  int bucket_num;
959  struct PeerInfo *pos;
960 
961  if (0 == GNUNET_memcmp (&my_identity_hash,
962  key))
963  return GNUNET_YES;
964  bucket_num = find_bucket (key);
965  GNUNET_assert (bucket_num >= 0);
967  key);
968  pos = k_buckets[bucket_num].head;
969  while (NULL != pos)
970  {
971  if ( (NULL != bloom) &&
972  (GNUNET_YES ==
974  &pos->phash)) )
975  {
976  pos = pos->next;
977  continue; /* Skip already checked entries */
978  }
979  other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->phash,
980  key);
981  if (other_bits > bits)
982  return GNUNET_NO;
983  if (other_bits == bits) /* We match the same number of bits */
984  return GNUNET_YES;
985  pos = pos->next;
986  }
987  /* No peers closer, we are the closest! */
988  return GNUNET_YES;
989 }
990 
991 
1009 static struct PeerInfo *
1010 select_peer (const struct GNUNET_HashCode *key,
1011  const struct GNUNET_CONTAINER_BloomFilter *bloom,
1012  uint32_t hops)
1013 {
1014  unsigned int bc;
1015  unsigned int count;
1016  unsigned int selected;
1017  struct PeerInfo *pos;
1018  unsigned int dist;
1019  unsigned int smallest_distance;
1020  struct PeerInfo *chosen;
1021 
1022  if (hops >= GDS_NSE_get ())
1023  {
1024  /* greedy selection (closest peer that is not in bloomfilter) */
1025  smallest_distance = UINT_MAX;
1026  chosen = NULL;
1027  for (bc = 0; bc <= closest_bucket; bc++)
1028  {
1029  pos = k_buckets[bc].head;
1030  count = 0;
1031  while ((pos != NULL) && (count < bucket_size))
1032  {
1033  if ( (NULL == bloom) ||
1034  (GNUNET_NO ==
1036  &pos->phash)))
1037  {
1038  dist = get_distance (key,
1039  &pos->phash);
1040  if (dist < smallest_distance)
1041  {
1042  chosen = pos;
1043  smallest_distance = dist;
1044  }
1045  }
1046  else
1047  {
1049  "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1050  GNUNET_i2s (pos->id),
1051  GNUNET_h2s (key));
1053  gettext_noop ("# Peers excluded from routing due to Bloomfilter"),
1054  1,
1055  GNUNET_NO);
1056  dist = get_distance (key,
1057  &pos->phash);
1058  if (dist < smallest_distance)
1059  {
1060  chosen = NULL;
1061  smallest_distance = dist;
1062  }
1063  }
1064  count++;
1065  pos = pos->next;
1066  }
1067  }
1068  if (NULL == chosen)
1070  gettext_noop ("# Peer selection failed"),
1071  1,
1072  GNUNET_NO);
1073  else
1075  "Selected peer `%s' in greedy routing for %s\n",
1076  GNUNET_i2s (chosen->id),
1077  GNUNET_h2s (key));
1078  return chosen;
1079  }
1080 
1081  /* select "random" peer */
1082  /* count number of peers that are available and not filtered */
1083  count = 0;
1084  for (bc = 0; bc <= closest_bucket; bc++)
1085  {
1086  pos = k_buckets[bc].head;
1087  while ( (NULL != pos) && (count < bucket_size) )
1088  {
1089  if ( (NULL != bloom) &&
1090  (GNUNET_YES ==
1092  &pos->phash)) )
1093  {
1095  gettext_noop
1096  ("# Peers excluded from routing due to Bloomfilter"),
1097  1, GNUNET_NO);
1099  "Excluded peer `%s' due to BF match in random routing for %s\n",
1100  GNUNET_i2s (pos->id),
1101  GNUNET_h2s (key));
1102  pos = pos->next;
1103  continue; /* Ignore bloomfiltered peers */
1104  }
1105  count++;
1106  pos = pos->next;
1107  }
1108  }
1109  if (0 == count) /* No peers to select from! */
1110  {
1112  gettext_noop ("# Peer selection failed"), 1,
1113  GNUNET_NO);
1114  return NULL;
1115  }
1116  /* Now actually choose a peer */
1118  count);
1119  count = 0;
1120  for (bc = 0; bc <= closest_bucket; bc++)
1121  {
1122  for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size)); pos = pos->next)
1123  {
1124  if ((bloom != NULL) &&
1125  (GNUNET_YES ==
1127  &pos->phash)))
1128  {
1129  continue; /* Ignore bloomfiltered peers */
1130  }
1131  if (0 == selected--)
1132  {
1134  "Selected peer `%s' in random routing for %s\n",
1135  GNUNET_i2s (pos->id),
1136  GNUNET_h2s (key));
1137  return pos;
1138  }
1139  }
1140  }
1141  GNUNET_break (0);
1142  return NULL;
1143 }
1144 
1145 
1159 static unsigned int
1161  struct GNUNET_CONTAINER_BloomFilter *bloom,
1162  uint32_t hop_count,
1163  uint32_t target_replication,
1164  struct PeerInfo ***targets)
1165 {
1166  unsigned int ret;
1167  unsigned int off;
1168  struct PeerInfo **rtargets;
1169  struct PeerInfo *nxt;
1170 
1171  GNUNET_assert (NULL != bloom);
1172  ret = get_forward_count (hop_count,
1173  target_replication);
1174  if (0 == ret)
1175  {
1176  *targets = NULL;
1177  return 0;
1178  }
1179  rtargets = GNUNET_new_array (ret,
1180  struct PeerInfo *);
1181  for (off = 0; off < ret; off++)
1182  {
1183  nxt = select_peer (key,
1184  bloom,
1185  hop_count);
1186  if (NULL == nxt)
1187  break;
1188  rtargets[off] = nxt;
1191  &nxt->phash));
1193  &nxt->phash);
1194  }
1196  "Selected %u/%u peers at hop %u for %s (target was %u)\n",
1197  off,
1198  GNUNET_CONTAINER_multipeermap_size (all_connected_peers),
1199  (unsigned int) hop_count,
1200  GNUNET_h2s (key),
1201  ret);
1202  if (0 == off)
1203  {
1204  GNUNET_free (rtargets);
1205  *targets = NULL;
1206  return 0;
1207  }
1208  *targets = rtargets;
1210  "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1211  GNUNET_h2s (key),
1212  off,
1213  ret);
1214  return off;
1215 }
1216 
1217 
1238 int
1241  uint32_t desired_replication_level,
1243  uint32_t hop_count,
1244  struct GNUNET_CONTAINER_BloomFilter *bf,
1245  const struct GNUNET_HashCode *key,
1246  unsigned int put_path_length,
1247  struct GNUNET_PeerIdentity *put_path,
1248  const void *data,
1249  size_t data_size)
1250 {
1251  unsigned int target_count;
1252  unsigned int i;
1253  struct PeerInfo **targets;
1254  struct PeerInfo *target;
1255  size_t msize;
1256  struct GNUNET_MQ_Envelope *env;
1257  struct PeerPutMessage *ppm;
1258  struct GNUNET_PeerIdentity *pp;
1259  unsigned int skip_count;
1260 
1261  GNUNET_assert (NULL != bf);
1263  "Adding myself (%s) to PUT bloomfilter for %s\n",
1265  GNUNET_h2s (key));
1267  &my_identity_hash);
1269  gettext_noop ("# PUT requests routed"),
1270  1,
1271  GNUNET_NO);
1272  target_count
1273  = get_target_peers (key,
1274  bf,
1275  hop_count,
1276  desired_replication_level,
1277  &targets);
1278  if (0 == target_count)
1279  {
1281  "Routing PUT for %s terminates after %u hops at %s\n",
1282  GNUNET_h2s (key),
1283  (unsigned int) hop_count,
1284  GNUNET_i2s (&my_identity));
1285  return GNUNET_NO;
1286  }
1287  msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size;
1288  if (msize + sizeof (struct PeerPutMessage)
1290  {
1291  put_path_length = 0;
1292  msize = data_size;
1293  }
1294  if (msize + sizeof (struct PeerPutMessage)
1296  {
1297  GNUNET_break (0);
1298  GNUNET_free (targets);
1299  return GNUNET_NO;
1300  }
1302  gettext_noop ("# PUT messages queued for transmission"),
1303  target_count,
1304  GNUNET_NO);
1305  skip_count = 0;
1306  for (i = 0; i < target_count; i++)
1307  {
1308  target = targets[i];
1310  {
1311  /* skip */
1313  gettext_noop ("# P2P messages dropped due to full queue"),
1314  1,
1315  GNUNET_NO);
1316  skip_count++;
1317  continue;
1318  }
1320  "Routing PUT for %s after %u hops to %s\n",
1321  GNUNET_h2s (key),
1322  (unsigned int) hop_count,
1323  GNUNET_i2s (target->id));
1324  env = GNUNET_MQ_msg_extra (ppm,
1325  msize,
1327  ppm->options = htonl (options);
1328  ppm->type = htonl (type);
1329  ppm->hop_count = htonl (hop_count + 1);
1330  ppm->desired_replication_level = htonl (desired_replication_level);
1331  ppm->put_path_length = htonl (put_path_length);
1332  ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1335  &target->phash));
1338  ppm->bloomfilter,
1339  DHT_BLOOM_SIZE));
1340  ppm->key = *key;
1341  pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1342  GNUNET_memcpy (pp,
1343  put_path,
1344  sizeof (struct GNUNET_PeerIdentity) * put_path_length);
1345  GNUNET_memcpy (&pp[put_path_length],
1346  data,
1347  data_size);
1348  GNUNET_MQ_send (target->mq,
1349  env);
1350  }
1351  GNUNET_free (targets);
1352  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1353 }
1354 
1355 
1373 int
1376  uint32_t desired_replication_level,
1377  uint32_t hop_count,
1378  const struct GNUNET_HashCode *key,
1379  const void *xquery,
1380  size_t xquery_size,
1381  struct GNUNET_BLOCK_Group *bg,
1382  struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1383 {
1384  unsigned int target_count;
1385  struct PeerInfo **targets;
1386  struct PeerInfo *target;
1387  struct GNUNET_MQ_Envelope *env;
1388  size_t msize;
1389  struct PeerGetMessage *pgm;
1390  char *xq;
1391  size_t reply_bf_size;
1392  void *reply_bf;
1393  unsigned int skip_count;
1394  uint32_t bf_nonce;
1395 
1396  GNUNET_assert (NULL != peer_bf);
1398  gettext_noop ("# GET requests routed"),
1399  1,
1400  GNUNET_NO);
1401  target_count = get_target_peers (key,
1402  peer_bf,
1403  hop_count,
1404  desired_replication_level,
1405  &targets);
1407  "Adding myself (%s) to GET bloomfilter for %s\n",
1409  GNUNET_h2s (key));
1411  &my_identity_hash);
1412  if (0 == target_count)
1413  {
1415  "Routing GET for %s terminates after %u hops at %s\n",
1416  GNUNET_h2s (key),
1417  (unsigned int) hop_count,
1418  GNUNET_i2s (&my_identity));
1419  return GNUNET_NO;
1420  }
1421  if (GNUNET_OK !=
1423  &bf_nonce,
1424  &reply_bf,
1425  &reply_bf_size))
1426  {
1427  reply_bf = NULL;
1428  reply_bf_size = 0;
1430  UINT32_MAX);
1431  }
1432  msize = xquery_size + reply_bf_size;
1433  if (msize + sizeof (struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
1434  {
1435  GNUNET_break (0);
1436  GNUNET_free_non_null (reply_bf);
1437  GNUNET_free (targets);
1438  return GNUNET_NO;
1439  }
1441  gettext_noop ("# GET messages queued for transmission"),
1442  target_count,
1443  GNUNET_NO);
1444  /* forward request */
1445  skip_count = 0;
1446  for (unsigned int i = 0; i < target_count; i++)
1447  {
1448  target = targets[i];
1450  {
1451  /* skip */
1453  gettext_noop ("# P2P messages dropped due to full queue"),
1454  1, GNUNET_NO);
1455  skip_count++;
1456  continue;
1457  }
1459  "Routing GET for %s after %u hops to %s\n",
1460  GNUNET_h2s (key),
1461  (unsigned int) hop_count,
1462  GNUNET_i2s (target->id));
1463  env = GNUNET_MQ_msg_extra (pgm,
1464  msize,
1466  pgm->options = htonl (options);
1467  pgm->type = htonl (type);
1468  pgm->hop_count = htonl (hop_count + 1);
1469  pgm->desired_replication_level = htonl (desired_replication_level);
1470  pgm->xquery_size = htonl (xquery_size);
1471  pgm->bf_mutator = bf_nonce;
1474  &target->phash));
1477  pgm->bloomfilter,
1478  DHT_BLOOM_SIZE));
1479  pgm->key = *key;
1480  xq = (char *) &pgm[1];
1481  GNUNET_memcpy (xq,
1482  xquery,
1483  xquery_size);
1484  GNUNET_memcpy (&xq[xquery_size],
1485  reply_bf,
1486  reply_bf_size);
1487  GNUNET_MQ_send (target->mq,
1488  env);
1489  }
1490  GNUNET_free (targets);
1491  GNUNET_free_non_null (reply_bf);
1492  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1493 }
1494 
1495 
1512 void
1514  enum GNUNET_BLOCK_Type type,
1516  const struct GNUNET_HashCode *key,
1517  unsigned int put_path_length,
1518  const struct GNUNET_PeerIdentity *put_path,
1519  unsigned int get_path_length,
1520  const struct GNUNET_PeerIdentity *get_path,
1521  const void *data,
1522  size_t data_size)
1523 {
1524  struct PeerInfo *pi;
1525  struct GNUNET_MQ_Envelope *env;
1526  size_t msize;
1527  struct PeerResultMessage *prm;
1528  struct GNUNET_PeerIdentity *paths;
1529 
1530  msize = data_size + (get_path_length + put_path_length) *
1531  sizeof (struct GNUNET_PeerIdentity);
1532  if ((msize + sizeof (struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
1533  (get_path_length >
1534  GNUNET_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1535  (put_path_length >
1536  GNUNET_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1537  (data_size > GNUNET_MAX_MESSAGE_SIZE))
1538  {
1539  GNUNET_break (0);
1540  return;
1541  }
1542  pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
1543  target);
1544  if (NULL == pi)
1545  {
1546  /* peer disconnected in the meantime, drop reply */
1548  "No matching peer for reply for key %s\n",
1549  GNUNET_h2s (key));
1550  return;
1551  }
1553  {
1554  /* skip */
1556  gettext_noop ("# P2P messages dropped due to full queue"),
1557  1,
1558  GNUNET_NO);
1560  "Peer queue full, ignoring reply for key %s\n",
1561  GNUNET_h2s (key));
1562  return;
1563  }
1564 
1566  "Forwarding reply for key %s to peer %s\n",
1567  GNUNET_h2s (key),
1568  GNUNET_i2s (target));
1570  gettext_noop
1571  ("# RESULT messages queued for transmission"), 1,
1572  GNUNET_NO);
1573  env = GNUNET_MQ_msg_extra (prm,
1574  msize,
1576  prm->type = htonl (type);
1577  prm->put_path_length = htonl (put_path_length);
1578  prm->get_path_length = htonl (get_path_length);
1579  prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1580  prm->key = *key;
1581  paths = (struct GNUNET_PeerIdentity *) &prm[1];
1582  GNUNET_memcpy (paths,
1583  put_path,
1584  put_path_length * sizeof (struct GNUNET_PeerIdentity));
1585  GNUNET_memcpy (&paths[put_path_length],
1586  get_path,
1587  get_path_length * sizeof (struct GNUNET_PeerIdentity));
1588  GNUNET_memcpy (&paths[put_path_length + get_path_length],
1589  data,
1590  data_size);
1591  GNUNET_MQ_send (pi->mq,
1592  env);
1593 }
1594 
1595 
1602 static void
1603 core_init (void *cls,
1604  const struct GNUNET_PeerIdentity *identity)
1605 {
1606  (void) cls;
1608  "CORE called, I am %s\n",
1609  GNUNET_i2s (identity));
1610  my_identity = *identity;
1611  GNUNET_CRYPTO_hash (identity,
1612  sizeof (struct GNUNET_PeerIdentity),
1613  &my_identity_hash);
1615 }
1616 
1617 
1625 static int
1627  const struct PeerPutMessage *put)
1628 {
1629  uint32_t putlen;
1630  uint16_t msize;
1631 
1632  (void) cls;
1633  msize = ntohs (put->header.size);
1634  putlen = ntohl (put->put_path_length);
1635  if ((msize <
1636  sizeof (struct PeerPutMessage) +
1637  putlen * sizeof (struct GNUNET_PeerIdentity)) ||
1638  (putlen >
1639  GNUNET_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
1640  {
1641  GNUNET_break_op (0);
1642  return GNUNET_SYSERR;
1643  }
1644  return GNUNET_OK;
1645 }
1646 
1647 
1654 static void
1656  const struct PeerPutMessage *put)
1657 {
1658  struct PeerInfo *peer = cls;
1659  const struct GNUNET_PeerIdentity *put_path;
1660  const void *payload;
1661  uint32_t putlen;
1662  uint16_t msize;
1663  size_t payload_size;
1665  struct GNUNET_CONTAINER_BloomFilter *bf;
1666  struct GNUNET_HashCode test_key;
1667  int forwarded;
1668  struct GNUNET_TIME_Absolute exp_time;
1669 
1670  exp_time = GNUNET_TIME_absolute_ntoh (put->expiration_time);
1671  if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
1672  {
1674  gettext_noop ("# Expired PUTs discarded"),
1675  1,
1676  GNUNET_NO);
1677  return;
1678  }
1679  msize = ntohs (put->header.size);
1680  putlen = ntohl (put->put_path_length);
1682  gettext_noop ("# P2P PUT requests received"),
1683  1,
1684  GNUNET_NO);
1686  gettext_noop ("# P2P PUT bytes received"),
1687  msize,
1688  GNUNET_NO);
1689  put_path = (const struct GNUNET_PeerIdentity *) &put[1];
1690  payload = &put_path[putlen];
1691  options = ntohl (put->options);
1692  payload_size = msize - (sizeof (struct PeerPutMessage) +
1693  putlen * sizeof (struct GNUNET_PeerIdentity));
1694 
1696  "PUT for `%s' from %s\n",
1697  GNUNET_h2s (&put->key),
1698  GNUNET_i2s (peer->id));
1700  {
1701  char *tmp;
1702  char *pp;
1703 
1704  pp = GNUNET_STRINGS_pp2s (put_path,
1705  putlen);
1708  "R5N PUT %s: %s->%s (%u, %u=>%u, PP: %s)\n",
1709  GNUNET_h2s (&put->key),
1710  GNUNET_i2s (peer->id),
1711  tmp,
1712  ntohl(put->hop_count),
1714  &put->key),
1716  &put->key),
1717  pp);
1718  GNUNET_free (pp);
1719  GNUNET_free (tmp);
1720  }
1721  switch (GNUNET_BLOCK_get_key
1723  ntohl (put->type),
1724  payload,
1725  payload_size,
1726  &test_key))
1727  {
1728  case GNUNET_YES:
1729  if (0 != memcmp (&test_key,
1730  &put->key,
1731  sizeof (struct GNUNET_HashCode)))
1732  {
1733  char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
1734 
1735  GNUNET_break_op (0);
1737  "PUT with key `%s' for block with key %s\n",
1738  put_s,
1739  GNUNET_h2s_full (&test_key));
1740  GNUNET_free (put_s);
1741  return;
1742  }
1743  break;
1744  case GNUNET_NO:
1745  GNUNET_break_op (0);
1746  return;
1747  case GNUNET_SYSERR:
1748  /* cannot verify, good luck */
1749  break;
1750  }
1751  if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
1752  {
1754  ntohl (put->type),
1755  NULL, /* query group */
1757  NULL, /* query */
1758  NULL, 0, /* xquery */
1759  payload,
1760  payload_size))
1761  {
1764  break;
1765 
1772  default:
1773  GNUNET_break_op (0);
1774  return;
1775  }
1776  }
1777 
1783  &peer->phash));
1784  {
1785  struct GNUNET_PeerIdentity pp[putlen + 1];
1786 
1787  /* extend 'put path' by sender */
1788  if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1789  {
1790 #if SANITY_CHECKS
1791  for (unsigned int i=0;i<=putlen;i++)
1792  {
1793  for (unsigned int j=0;j<i;j++)
1794  {
1795  GNUNET_break (0 != memcmp (&pp[i],
1796  &pp[j],
1797  sizeof (struct GNUNET_PeerIdentity)));
1798  }
1799  GNUNET_break (0 != memcmp (&pp[i],
1800  peer->id,
1801  sizeof (struct GNUNET_PeerIdentity)));
1802  }
1803 #endif
1804  GNUNET_memcpy (pp,
1805  put_path,
1806  putlen * sizeof (struct GNUNET_PeerIdentity));
1807  pp[putlen] = *peer->id;
1808  putlen++;
1809  }
1810  else
1811  putlen = 0;
1812 
1813  /* give to local clients */
1814  GDS_CLIENTS_handle_reply (exp_time,
1815  &put->key,
1816  0,
1817  NULL,
1818  putlen,
1819  pp,
1820  ntohl (put->type),
1821  payload_size,
1822  payload);
1823  /* store locally */
1824  if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1825  (GDS_am_closest_peer (&put->key, bf)))
1826  GDS_DATACACHE_handle_put (exp_time,
1827  &put->key,
1828  putlen,
1829  pp,
1830  ntohl (put->type),
1831  payload_size,
1832  payload);
1833  /* route to other peers */
1834  forwarded = GDS_NEIGHBOURS_handle_put (ntohl (put->type),
1835  options,
1836  ntohl (put->desired_replication_level),
1837  exp_time,
1838  ntohl (put->hop_count),
1839  bf,
1840  &put->key,
1841  putlen,
1842  pp,
1843  payload,
1844  payload_size);
1845  /* notify monitoring clients */
1846  GDS_CLIENTS_process_put (options
1847  | ( (GNUNET_OK == forwarded)
1849  : 0 ),
1850  ntohl (put->type),
1851  ntohl (put->hop_count),
1852  ntohl (put->desired_replication_level),
1853  putlen, pp,
1854  exp_time,
1855  &put->key,
1856  payload,
1857  payload_size);
1858  }
1860 }
1861 
1862 
1871 static void
1873  const struct GNUNET_HashCode *key,
1874  struct GNUNET_BLOCK_Group *bg)
1875 {
1876  int bucket_idx;
1877  struct PeerBucket *bucket;
1878  struct PeerInfo *peer;
1879  unsigned int choice;
1880  const struct GNUNET_HELLO_Message *hello;
1881  size_t hello_size;
1882 
1883  /* first, check about our own HELLO */
1884  if (NULL != GDS_my_hello)
1885  {
1886  hello_size = GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) GDS_my_hello);
1887  GNUNET_break (hello_size >= sizeof (struct GNUNET_MessageHeader));
1891  bg,
1894  NULL, 0,
1895  GDS_my_hello,
1896  hello_size))
1897  {
1901  key,
1902  0,
1903  NULL,
1904  0,
1905  NULL,
1906  GDS_my_hello,
1907  hello_size);
1908  }
1909  else
1910  {
1912  gettext_noop ("# FIND PEER requests ignored due to Bloomfilter"),
1913  1,
1914  GNUNET_NO);
1915  }
1916  }
1917  else
1918  {
1920  gettext_noop ("# FIND PEER requests ignored due to lack of HELLO"),
1921  1,
1922  GNUNET_NO);
1923  }
1924 
1925  /* then, also consider sending a random HELLO from the closest bucket */
1926  if (0 == memcmp (&my_identity_hash,
1927  key,
1928  sizeof (struct GNUNET_HashCode)))
1929  bucket_idx = closest_bucket;
1930  else
1931  bucket_idx = GNUNET_MIN ((int) closest_bucket,
1932  find_bucket (key));
1933  if (bucket_idx < 0)
1934  return;
1935  bucket = &k_buckets[bucket_idx];
1936  if (bucket->peers_size == 0)
1937  return;
1939  bucket->peers_size);
1940  peer = bucket->head;
1941  while (choice > 0)
1942  {
1943  GNUNET_assert (NULL != peer);
1944  peer = peer->next;
1945  choice--;
1946  }
1947  choice = bucket->peers_size;
1948  do
1949  {
1950  peer = peer->next;
1951  if (0 == choice--)
1952  return; /* no non-masked peer available */
1953  if (NULL == peer)
1954  peer = bucket->head;
1955  hello = GDS_HELLO_get (peer->id);
1956  } while ( (NULL == hello) ||
1960  bg,
1962  &peer->phash,
1963  NULL, 0,
1964  hello,
1965  (hello_size = GNUNET_HELLO_size (hello)))) );
1970  key,
1971  0,
1972  NULL,
1973  0,
1974  NULL,
1975  hello,
1976  hello_size);
1977 }
1978 
1979 
1994 static void
1996  enum GNUNET_BLOCK_Type type,
1998  const struct GNUNET_HashCode *key,
1999  unsigned int put_path_length,
2000  const struct GNUNET_PeerIdentity *put_path,
2001  unsigned int get_path_length,
2002  const struct GNUNET_PeerIdentity *get_path,
2003  const void *data,
2004  size_t data_size)
2005 {
2006  struct PeerInfo *peer = cls;
2007  char *pp;
2008 
2009  pp = GNUNET_STRINGS_pp2s (put_path,
2010  put_path_length);
2012  "Found local result for %s (PP: %s)\n",
2013  GNUNET_h2s (key),
2014  pp);
2015  GNUNET_free (pp);
2017  type,
2018  expiration_time,
2019  key,
2020  put_path_length, put_path,
2021  get_path_length, get_path,
2022  data, data_size);
2023 }
2024 
2025 
2033 static int
2035  const struct PeerGetMessage *get)
2036 {
2037  uint32_t xquery_size;
2038  uint16_t msize;
2039 
2040  (void) cls;
2041  msize = ntohs (get->header.size);
2042  xquery_size = ntohl (get->xquery_size);
2043  if (msize < sizeof (struct PeerGetMessage) + xquery_size)
2044  {
2045  GNUNET_break_op (0);
2046  return GNUNET_SYSERR;
2047  }
2048  return GNUNET_OK;
2049 }
2050 
2051 
2058 static void
2060  const struct PeerGetMessage *get)
2061 {
2062  struct PeerInfo *peer = cls;
2063  uint32_t xquery_size;
2064  size_t reply_bf_size;
2065  uint16_t msize;
2066  enum GNUNET_BLOCK_Type type;
2069  struct GNUNET_BLOCK_Group *bg;
2070  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2071  const char *xquery;
2072  int forwarded;
2073 
2074  /* parse and validate message */
2075  msize = ntohs (get->header.size);
2076  xquery_size = ntohl (get->xquery_size);
2077  reply_bf_size = msize - (sizeof (struct PeerGetMessage) + xquery_size);
2078  type = ntohl (get->type);
2079  options = ntohl (get->options);
2080  xquery = (const char *) &get[1];
2082  gettext_noop ("# P2P GET requests received"),
2083  1,
2084  GNUNET_NO);
2086  gettext_noop ("# P2P GET bytes received"),
2087  msize,
2088  GNUNET_NO);
2090  {
2091  char *tmp;
2092 
2095  "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
2096  GNUNET_h2s (&get->key),
2097  GNUNET_i2s (peer->id),
2098  tmp,
2099  ntohl(get->hop_count),
2101  &get->key),
2103  &get->key),
2104  ntohl(get->xquery_size),
2105  xquery);
2106  GNUNET_free (tmp);
2107  }
2108  eval
2110  type,
2111  NULL,
2113  &get->key,
2114  xquery,
2115  xquery_size,
2116  NULL,
2117  0);
2119  {
2120  /* request invalid or block type not supported */
2122  return;
2123  }
2124  peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
2129  &peer->phash));
2131  type,
2132  get->bf_mutator,
2133  &xquery[xquery_size],
2134  reply_bf_size,
2135  "filter-size",
2136  reply_bf_size,
2137  NULL);
2139  "GET for %s at %s after %u hops\n",
2140  GNUNET_h2s (&get->key),
2142  (unsigned int) ntohl (get->hop_count));
2143  /* local lookup (this may update the reply_bf) */
2144  if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2145  (GDS_am_closest_peer (&get->key,
2146  peer_bf)))
2147  {
2148  if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
2149  {
2151  gettext_noop ("# P2P FIND PEER requests processed"),
2152  1,
2153  GNUNET_NO);
2154  handle_find_peer (peer->id,
2155  &get->key,
2156  bg);
2157  }
2158  else
2159  {
2160  eval = GDS_DATACACHE_handle_get (&get->key,
2161  type,
2162  xquery,
2163  xquery_size,
2164  bg,
2166  peer);
2167  }
2168  }
2169  else
2170  {
2172  gettext_noop ("# P2P GET requests ONLY routed"),
2173  1,
2174  GNUNET_NO);
2175  }
2176 
2177  /* remember request for routing replies */
2178  GDS_ROUTING_add (peer->id,
2179  type,
2180  bg, /* bg now owned by routing, but valid at least until end of this function! */
2181  options,
2182  &get->key,
2183  xquery,
2184  xquery_size);
2185 
2186  /* P2P forwarding */
2187  forwarded = GNUNET_NO;
2188  if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
2189  forwarded = GDS_NEIGHBOURS_handle_get (type,
2190  options,
2191  ntohl (get->desired_replication_level),
2192  ntohl (get->hop_count),
2193  &get->key,
2194  xquery,
2195  xquery_size,
2196  bg,
2197  peer_bf);
2198  GDS_CLIENTS_process_get (options
2199  | (GNUNET_OK == forwarded)
2200  ? GNUNET_DHT_RO_LAST_HOP : 0,
2201  type,
2202  ntohl (get->hop_count),
2203  ntohl (get->desired_replication_level),
2204  0,
2205  NULL,
2206  &get->key);
2207 
2208  /* clean up; note that 'bg' is owned by routing now! */
2210 }
2211 
2212 
2220 static int
2222  const struct PeerResultMessage *prm)
2223 {
2224  uint32_t get_path_length;
2225  uint32_t put_path_length;
2226  uint16_t msize;
2227 
2228  (void) cls;
2229  msize = ntohs (prm->header.size);
2230  put_path_length = ntohl (prm->put_path_length);
2231  get_path_length = ntohl (prm->get_path_length);
2232  if ((msize <
2233  sizeof (struct PeerResultMessage) + (get_path_length +
2234  put_path_length) *
2235  sizeof (struct GNUNET_PeerIdentity)) ||
2236  (get_path_length >
2237  GNUNET_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
2238  (put_path_length >
2239  GNUNET_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2240  {
2241  GNUNET_break_op (0);
2242  return GNUNET_SYSERR;
2243  }
2244  return GNUNET_OK;
2245 }
2246 
2247 
2261 static void
2263  const struct GNUNET_HashCode *key,
2264  unsigned int get_path_length,
2265  const struct GNUNET_PeerIdentity *get_path,
2266  unsigned int put_path_length,
2267  const struct GNUNET_PeerIdentity *put_path,
2268  enum GNUNET_BLOCK_Type type,
2269  size_t data_size,
2270  const void *data)
2271 {
2272  /* forward to local clients */
2273  GDS_CLIENTS_handle_reply (expiration_time,
2274  key,
2275  get_path_length,
2276  get_path,
2277  put_path_length,
2278  put_path,
2279  type,
2280  data_size,
2281  data);
2283  get_path,
2284  get_path_length,
2285  put_path,
2286  put_path_length,
2287  expiration_time,
2288  key,
2289  data,
2290  data_size);
2291  if (GNUNET_YES == cache_results)
2292  {
2293  struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length];
2294 
2295  GNUNET_memcpy (xput_path,
2296  put_path,
2297  put_path_length * sizeof (struct GNUNET_PeerIdentity));
2298  GNUNET_memcpy (&xput_path[put_path_length],
2299  get_path,
2300  get_path_length * sizeof (struct GNUNET_PeerIdentity));
2301 
2302  GDS_DATACACHE_handle_put (expiration_time,
2303  key,
2304  get_path_length + put_path_length,
2305  xput_path,
2306  type,
2307  data_size,
2308  data);
2309  }
2310  /* forward to other peers */
2311  GDS_ROUTING_process (type,
2312  expiration_time,
2313  key,
2314  put_path_length,
2315  put_path,
2316  get_path_length,
2317  get_path,
2318  data,
2319  data_size);
2320 }
2321 
2322 
2329 static void
2331  const struct PeerResultMessage *prm)
2332 {
2333  struct PeerInfo *peer = cls;
2334  const struct GNUNET_PeerIdentity *put_path;
2335  const struct GNUNET_PeerIdentity *get_path;
2336  const void *data;
2337  uint32_t get_path_length;
2338  uint32_t put_path_length;
2339  uint16_t msize;
2340  size_t data_size;
2341  enum GNUNET_BLOCK_Type type;
2342  struct GNUNET_TIME_Absolute exp_time;
2343 
2344  /* parse and validate message */
2345  exp_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time);
2346  if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
2347  {
2349  gettext_noop ("# Expired results discarded"),
2350  1,
2351  GNUNET_NO);
2352  return;
2353  }
2354  msize = ntohs (prm->header.size);
2355  put_path_length = ntohl (prm->put_path_length);
2356  get_path_length = ntohl (prm->get_path_length);
2357  put_path = (const struct GNUNET_PeerIdentity *) &prm[1];
2358  get_path = &put_path[put_path_length];
2359  type = ntohl (prm->type);
2360  data = (const void *) &get_path[get_path_length];
2361  data_size = msize - (sizeof (struct PeerResultMessage) +
2362  (get_path_length +
2363  put_path_length) * sizeof (struct GNUNET_PeerIdentity));
2365  gettext_noop ("# P2P RESULTS received"),
2366  1,
2367  GNUNET_NO);
2369  gettext_noop ("# P2P RESULT bytes received"),
2370  msize,
2371  GNUNET_NO);
2373  {
2374  char *tmp;
2375  char *pp;
2376  char *gp;
2377 
2378  gp = GNUNET_STRINGS_pp2s (get_path,
2379  get_path_length);
2380  pp = GNUNET_STRINGS_pp2s (put_path,
2381  put_path_length);
2384  "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n",
2385  GNUNET_h2s (&prm->key),
2386  GNUNET_i2s (peer->id),
2387  tmp,
2388  gp,
2389  pp);
2390  GNUNET_free (gp);
2391  GNUNET_free (pp);
2392  GNUNET_free (tmp);
2393  }
2394  /* if we got a HELLO, consider it for our own routing table */
2395  if (GNUNET_BLOCK_TYPE_DHT_HELLO == type)
2396  {
2397  const struct GNUNET_MessageHeader *h;
2398  struct GNUNET_PeerIdentity pid;
2399 
2400  /* Should be a HELLO, validate and consider using it! */
2401  if (data_size < sizeof (struct GNUNET_HELLO_Message))
2402  {
2403  GNUNET_break_op (0);
2404  return;
2405  }
2406  h = data;
2407  if (data_size != ntohs (h->size))
2408  {
2409  GNUNET_break_op (0);
2410  return;
2411  }
2412  if (GNUNET_OK !=
2413  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h,
2414  &pid))
2415  {
2416  GNUNET_break_op (0);
2417  return;
2418  }
2419  if ( (GNUNET_YES != disable_try_connect) &&
2420  (0 != memcmp (&my_identity,
2421  &pid,
2422  sizeof (struct GNUNET_PeerIdentity))) )
2423  try_connect (&pid,
2424  h);
2425  }
2426 
2427  /* First, check if 'peer' is already on the path, and if
2428  so, truncate it instead of expanding. */
2429  for (unsigned int i=0;i<=get_path_length;i++)
2430  if (0 == memcmp (&get_path[i],
2431  peer->id,
2432  sizeof (struct GNUNET_PeerIdentity)))
2433  {
2434  process_reply_with_path (exp_time,
2435  &prm->key,
2436  i,
2437  get_path,
2438  put_path_length,
2439  put_path,
2440  type,
2441  data_size,
2442  data);
2443  return;
2444  }
2445 
2446  /* Need to append 'peer' to 'get_path' (normal case) */
2447  {
2448  struct GNUNET_PeerIdentity xget_path[get_path_length + 1];
2449 
2450  GNUNET_memcpy (xget_path,
2451  get_path,
2452  get_path_length * sizeof (struct GNUNET_PeerIdentity));
2453  xget_path[get_path_length] = *peer->id;
2454 
2455  process_reply_with_path (exp_time,
2456  &prm->key,
2457  get_path_length + 1,
2458  xget_path,
2459  put_path_length,
2460  put_path,
2461  type,
2462  data_size,
2463  data);
2464  }
2465 }
2466 
2467 
2473 int
2475 {
2476  struct GNUNET_MQ_MessageHandler core_handlers[] = {
2477  GNUNET_MQ_hd_var_size (dht_p2p_get,
2479  struct PeerGetMessage,
2480  NULL),
2481  GNUNET_MQ_hd_var_size (dht_p2p_put,
2483  struct PeerPutMessage,
2484  NULL),
2485  GNUNET_MQ_hd_var_size (dht_p2p_result,
2487  struct PeerResultMessage,
2488  NULL),
2490  };
2491  unsigned long long temp_config_num;
2492 
2495  "DHT",
2496  "DISABLE_TRY_CONNECT");
2497  if (GNUNET_OK ==
2499  "DHT",
2500  "bucket_size",
2501  &temp_config_num))
2502  bucket_size = (unsigned int) temp_config_num;
2505  "DHT",
2506  "CACHE_RESULTS");
2507 
2509  (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO;
2511  core_api = GNUNET_CORE_connect (GDS_cfg,
2512  NULL,
2513  &core_init,
2516  core_handlers);
2517  if (NULL == core_api)
2518  return GNUNET_SYSERR;
2519  all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256,
2520  GNUNET_YES);
2521  all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256,
2522  GNUNET_NO);
2523  return GNUNET_OK;
2524 }
2525 
2526 
2530 void
2532 {
2533  if (NULL == core_api)
2534  return;
2535  GNUNET_CORE_disconnect (core_api);
2536  core_api = NULL;
2537  GNUNET_assert (0 ==
2538  GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
2539  GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers);
2540  all_connected_peers = NULL;
2541  GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
2543  NULL);
2544  GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers);
2545  all_desired_peers = NULL;
2547  ats_ch = NULL;
2548  GNUNET_assert (NULL == find_peer_task);
2549 }
2550 
2551 
2557 struct GNUNET_PeerIdentity *
2559 {
2560  return &my_identity;
2561 }
2562 
2563 
2564 /* end of gnunet-service-dht_neighbours.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
Block does not match query (invalid result)
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id()
Get the ID of the local node.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
static unsigned int closest_bucket
The lowest currently used bucket, initially 0 (for 0-bits matching bucket).
int GNUNET_HELLO_get_id(const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer)
Get the peer identity from a HELLO message.
Definition: hello.c:668
uint32_t type
Content type.
static unsigned int get_distance(const struct GNUNET_HashCode *target, const struct GNUNET_HashCode *have)
Compute the distance between have and target as a 32-bit value.
struct GNUNET_MessageHeader * GDS_my_hello
Our HELLO.
GNUnet DHT globals.
uint32_t type
Desired content type.
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
We should keep track of the route that the message took in the P2P network.
A HELLO message is used to exchange information about transports with other peers.
#define DHT_MINIMUM_FIND_PEER_INTERVAL
How long at least to wait before sending another find peer request.
static struct PeerBucket k_buckets[sizeof(struct GNUNET_HashCode) *8]
The buckets.
Entry in linked list for all offer-HELLO requests.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:670
struct PeerInfo * prev
Prev peer entry (DLL)
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
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 int cache_results
Do we cache all results that we are routing in the local datacache?
uint64_t rel_value_us
The actual value.
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...
uint32_t put_path_length
Length of the PUT path that follows (if tracked).
struct PeerInfo * next
Next peer entry (DLL)
uint32_t hop_count
Hop count.
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2481
static int check_dht_p2p_result(void *cls, const struct PeerResultMessage *prm)
Check validity of p2p result message.
void GDS_NEIGHBOURS_done()
Shutdown neighbours subsystem.
Context for the core service connection.
Definition: core_api.c:78
#define MAXIMUM_PENDING_PER_PEER
Maximum allowed number of pending messages per peer.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
static void update_connect_preferences()
Update our preferences for connectivity as given to ATS.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
#define GNUNET_TIME_UNIT_MINUTES
One minute.
static void handle_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Core handler for p2p get requests.
unsigned int GNUNET_CRYPTO_hash_matching_bits(const struct GNUNET_HashCode *first, const struct GNUNET_HashCode *second)
Determine how many low order bits match in two struct GNUNET_HashCodes.
Definition: crypto_hash.c:256
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
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:245
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_CONSTANTS_BLOOMFILTER_K
K-value that must be used for the bloom filters in &#39;GET&#39; queries.
static void handle_find_peer(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_HashCode *key, struct GNUNET_BLOCK_Group *bg)
We have received a FIND PEER request.
static struct GNUNET_SCHEDULER_Task * find_peer_task
Task that sends FIND PEER requests.
uint32_t put_path_length
Length of the PUT path that follows (if tracked).
struct GNUNET_SERVICE_Handle * GDS_service
Handle for the service.
struct PeerInfo * head
Head of DLL.
static int find_bucket(const struct GNUNET_HashCode *hc)
Find the optimal bucket for this key.
Block does not match xquery (valid result, not relevant for the request)
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.
uint32_t get_path_length
Length of the GET path that follows (if tracked).
#define GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION
After how long do we expire an address in a HELLO that we just validated? This value is also used for...
unsigned int peers_size
Number of peers in the bucket.
#define GNUNET_NO
Definition: gnunet_common.h:81
static unsigned int get_forward_count(uint32_t hop_count, uint32_t target_replication)
To how many peers should we (on average) forward the request to obtain the desired target_replication...
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
struct GNUNET_HashCode phash
Hash of id.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void core_init(void *cls, const struct GNUNET_PeerIdentity *identity)
To be called on core init/fail.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
uint32_t options
Processing options.
struct GNUNET_HashCode key
The key we are looking for.
Default behavior.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GDS_CLIENTS_process_get(uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode *key)
Check if some client is monitoring GET messages and notify them in that case.
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
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).
static int ret
Final status code.
Definition: gnunet-arm.c:89
#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...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
GNUnet DHT integration with peerinfo.
void GDS_CLIENTS_process_put(uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const void *data, size_t size)
Check if some client is monitoring PUT messages and notify them in that case.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static unsigned int newly_found_peers
How many peers have we added since we sent out our last find peer request?
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
#define FIND_PEER_REPLICATION_LEVEL
Desired replication level for FIND PEER requests.
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int 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:379
struct GNUNET_HashCode my_identity_hash
Hash of the identity of this peer.
struct GNUNET_ATS_ConnectivitySuggestHandle * GNUNET_ATS_connectivity_suggest(struct GNUNET_ATS_ConnectivityHandle *ch, const struct GNUNET_PeerIdentity *peer, uint32_t strength)
We would like to receive address suggestions for a peer.
static int 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&#39;t get duplica...
#define DHT_MAXIMUM_FIND_PEER_INTERVAL
How long at most to wait before sending another find peer request.
uint32_t desired_replication_level
Desired replication level for this request.
static int disable_try_connect
Option for testing that disables the &#39;connect&#39; function of the DHT.
struct GNUNET_BLOCK_Context * GDS_block_context
Our handle to the BLOCK library.
static int update_desire_strength(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each peer in all_desired_peers during update_connect_preferences() if we have rea...
int peer_bucket
Which bucket is this peer in?
Flag given to monitors if this was the last hop for a GET/PUT.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
static int free_connect_info(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Function called for all entries in all_desired_peers to clean up.
struct GNUNET_HashCode key
The key we are storing under.
This is a &#39;FIND-PEER&#39; request, so approximate results are fine.
#define GNUNET_memcpy(dst, src, n)
struct GNUNET_TRANSPORT_OfferHelloHandle * oh
Handle to active HELLO offer operation, or NULL.
static char * value
Value of the record to add/remove.
#define MAX_BUCKETS
How many buckets will we allow total.
int GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
Valid result, but suppressed because it is a duplicate.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
Information about a peer that we would like to connect to.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:335
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:85
char * GNUNET_STRINGS_pp2s(const struct GNUNET_PeerIdentity *pids, unsigned int num_pids)
Convert a peer path to a human-readable string.
Definition: strings.c:99
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT.
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:1273
enum GNUNET_BLOCK_EvaluationResult GNUNET_BLOCK_evaluate(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *group, enum GNUNET_BLOCK_EvaluationOptions eo, 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 a reply or a request.
Definition: block.c:339
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
void GDS_DATACACHE_handle_put(struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data)
Handle a datum we&#39;ve received from another peer.
int 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.
Last possible valid result.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
Handle for ATS address suggestion requests.
struct PeerInfo * tail
Tail of DLL.
static void handle_dht_p2p_result(void *cls, const struct PeerResultMessage *prm)
Core handler for p2p result messages.
uint32_t hop_count
Hop count.
void GDS_CLIENTS_process_get_resp(enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const void *data, size_t size)
Check if some client is monitoring GET RESP messages and notify them in that case.
int GNUNET_BLOCK_group_serialize(struct GNUNET_BLOCK_Group *bg, uint32_t *nonce, void **raw_data, size_t *raw_data_size)
Serialize state of a block group.
Definition: block.c:181
GNUnet DHT tracking of requests for routing replies.
Internal representation of the hash map.
Type of a block that contains a HELLO for a peer (for DHT and CADET find-peer operations).
A 512-bit hashcode.
Message handler for a specific message type.
GNUNET_DHT_RouteOption
Options for routing.
uint32_t desired_replication_level
Replication level for this message.
void GNUNET_TRANSPORT_offer_hello_cancel(struct GNUNET_TRANSPORT_OfferHelloHandle *ohh)
Cancel the request to transport to offer the HELLO message.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_GET
Peer tries to find data in DHT.
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
void GDS_ROUTING_process(enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a reply (route to origin).
struct GNUNET_ATS_ConnectivitySuggestHandle * sh
Handle to active connectivity suggestion operation, or NULL.
The block is obtained from the local database, skip cryptographic checks.
Peers are grouped into buckets.
static void handle_local_result(void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a result from local datacache for a GET operation.
#define MAXIMUM_REPLICATION_LEVEL
Maximum allowed replication level for all requests.
uint32_t bf_mutator
Bloomfilter mutator.
Valid result, and there may be more.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
int GNUNET_CRYPTO_hash_get_bit(const struct GNUNET_HashCode *code, unsigned int bit)
Obtain a bit from a hashcode.
Definition: crypto_hash.c:236
Entry for a peer in a bucket.
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:694
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:732
char * getenv()
GNUNET_BLOCK_EvaluationResult
Possible ways for how a block may relate to a query.
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static void process_reply_with_path(struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data)
Process a reply, after the get_path has been updated.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
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.
static int check_dht_p2p_put(void *cls, const struct PeerPutMessage *put)
Check validity of a p2p put request.
GNUnet DHT routing code.
static struct GNUNET_CONTAINER_MultiPeerMap * all_connected_peers
Hash map of all CORE-connected peers, for easy removal from k_buckets on disconnect.
static unsigned long long payload
How much data are we currently storing in the database?
struct GNUNET_BLOCK_Group * GNUNET_BLOCK_group_create(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, uint32_t nonce, const void *raw_data, size_t raw_data_size,...)
Create a new block group.
Definition: block.c:290
static struct GNUNET_CORE_Handle * core_api
Handle to CORE.
static int check_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Check validity of p2p get request.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
uint32_t xquery_size
Size of the extended query.
int GDS_NEIGHBOURS_handle_get(enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, uint32_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.
uint32_t strength
How much would we like to connect to this peer?
Specified block type not supported by this plugin.
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
Handle to a message queue.
Definition: mq.c:85
static void handle_dht_p2p_put(void *cls, const struct PeerPutMessage *put)
Core handler for p2p put requests.
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.
uint32_t options
Processing options.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
struct GNUNET_ATS_ConnectivityHandle * GNUNET_ATS_connectivity_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the ATS connectivity suggestion client handle.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
GNUnet DHT service&#39;s datacache integration.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
The identity of the host (wraps the signing key of the peer).
#define GNUNET_PACKED
gcc-ism to get packed structs.
static struct PendingResolutions * head
Head of list of pending resolution requests.
Definition: gnunet-ats.c:231
uint32_t type
Content type.
struct GNUNET_TIME_Relative hello_expiration
Hello address expiration.
const struct GNUNET_PeerIdentity * id
What is the identity of the peer?
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.
Query format does not match block type (invalid query).
Automatic transport selection and outbound bandwidth determination.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
static void try_connect(const struct GNUNET_PeerIdentity *pid, const struct GNUNET_MessageHeader *h)
Consider if we want to connect to a given peer, and if so let ATS know.
const struct GNUNET_HELLO_Message * GDS_HELLO_get(const struct GNUNET_PeerIdentity *peer)
Obtain a peer&#39;s HELLO if available.
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...
struct GNUNET_TRANSPORT_OfferHelloHandle * GNUNET_TRANSPORT_offer_hello(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_MessageHeader *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Offer the transport service the HELLO of another peer.
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:649
Block group data.
static struct GNUNET_ATS_ConnectivityHandle * ats_ch
Handle to ATS connectivity.
#define LOG_TRAFFIC(kind,...)
static void handle_core_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls)
Method called whenever a peer disconnects.
static unsigned int bucket_size
Maximum size for each bucket.
enum GNUNET_BLOCK_EvaluationResult 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&#39;ve received from another peer.
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
static struct GNUNET_CONTAINER_MultiPeerMap * all_desired_peers
Hash map of all peers we would like to be connected to.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
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.
#define GNUNET_YES
Definition: gnunet_common.h:80
static int log_route_details_stderr
Should routing details be logged to stderr (for debugging)?
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:353
double GDS_NSE_get()
Return the log of the current network size estimate.
int GDS_NEIGHBOURS_init()
Initialize neighbours subsystem.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_MQ_Handle * mq
Handle for sending messages to this peer.
Block to store a cadet regex state.
static unsigned int get_target_peers(const struct GNUNET_HashCode *key, struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hop_count, uint32_t target_replication, struct PeerInfo ***targets)
Compute the set of peers that the given request should be forwarded to.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
Configuration we use.
int 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".
uint32_t data
The data value.
Handle to the ATS subsystem for connectivity management.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
Peer is storing data in DHT.
void GNUNET_ATS_connectivity_done(struct GNUNET_ATS_ConnectivityHandle *ch)
Client is done with ATS connectivity management, release resources.
static size_t data_size
Number of bytes in data.
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
struct GNUNET_HashCode key
The key of the corresponding GET request.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:654
Query is valid, no reply given.
void GDS_NEIGHBOURS_handle_reply(const struct GNUNET_PeerIdentity *target, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a reply (route to origin).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associcated with a filter in memory, flush to drive if needed (do not free the space o...
static void offer_hello_done(void *cls)
Function called when GNUNET_TRANSPORT_offer_hello() is done.
static void * handle_core_connect(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a peer connects.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
Each peer along the way should look at &#39;enc&#39; (otherwise only the k-peers closest to the key should lo...
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
GNUnet DHT integration with NSE.
void GDS_CLIENTS_handle_reply(struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data)
Handle a reply we&#39;ve received from another peer.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
Data is returned to peer from DHT.
Time for relative time used by GNUnet, in microseconds.
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition: block.c:206
int 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:410
#define gettext_noop(String)
Definition: gettext.h:69
uint32_t bits[512/8/sizeof(uint32_t)]
#define DEFAULT_BUCKET_SIZE
What is the maximum number of peers in a given bucket.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
int GDS_NEIGHBOURS_handle_put(enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, struct GNUNET_TIME_Absolute expiration_time, uint32_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *key, unsigned int put_path_length, struct GNUNET_PeerIdentity *put_path, const void *data, size_t data_size)
Perform a PUT operation.