GNUnet  0.11.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, 2021 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", \
50  __VA_ARGS__)
51 
55 #define SANITY_CHECKS 1
56 
60 #define MAX_BUCKETS sizeof(struct GNUNET_HashCode) * 8
61 
65 #define DEFAULT_BUCKET_SIZE 8
66 
70 #define FIND_PEER_REPLICATION_LEVEL 4
71 
75 #define MAXIMUM_REPLICATION_LEVEL 16
76 
80 #define MAXIMUM_PENDING_PER_PEER 64
81 
85 #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
86  GNUNET_TIME_UNIT_SECONDS, 30)
87 
91 #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
92  GNUNET_TIME_UNIT_MINUTES, 10)
93 
97 #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
98 
103 
104 
106 
111 {
116 
121 
125  uint32_t type GNUNET_PACKED;
126 
131 
136 
141 
146 
151 
156 
157  /* put path (if tracked) */
158 
159  /* Payload */
160 };
161 
162 
167 {
172 
176  uint32_t type GNUNET_PACKED;
177 
182 
186  uint32_t get_path_length GNUNET_PACKED;
187 
192 
196  struct GNUNET_HashCode key;
197 
198  /* put path (if tracked) */
199 
200  /* get path (if tracked) */
201 
202  /* Payload */
203 };
204 
205 
210 {
215 
220 
224  uint32_t type GNUNET_PACKED;
225 
230 
235 
239  uint32_t xquery_size;
240 
244  uint32_t bf_mutator;
245 
250 
254  struct GNUNET_HashCode key;
255 
256  /* xquery */
257 
258  /* result bloomfilter */
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 
304 {
308  struct PeerInfo *head;
309 
313  struct PeerInfo *tail;
314 
318  unsigned int peers_size;
319 };
320 
321 
326 {
331 
336 
340  uint32_t strength;
341 };
342 
343 
347 static int cache_results;
348 
353 
357 static unsigned int closest_bucket;
358 
363 static unsigned int newly_found_peers;
364 
369 
374 
380 
386 
390 static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
391 
396 
401 
406 
411 
416 
417 
425 static int
426 find_bucket (const struct GNUNET_HashCode *hc)
427 {
428  unsigned int bits;
429 
431  if (bits == MAX_BUCKETS)
432  {
433  /* How can all bits match? Got my own ID? */
434  GNUNET_break (0);
435  return GNUNET_SYSERR;
436  }
437  return MAX_BUCKETS - bits - 1;
438 }
439 
440 
447 static void
448 offer_hello_done (void *cls)
449 {
450  struct ConnectInfo *ci = cls;
451 
452  ci->oh = NULL;
453 }
454 
455 
464 static int
465 free_connect_info (void *cls,
466  const struct GNUNET_PeerIdentity *peer,
467  void *value)
468 {
469  struct ConnectInfo *ci = value;
470 
471  (void) cls;
473  GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
474  peer,
475  ci));
476  if (NULL != ci->sh)
477  {
479  ci->sh = NULL;
480  }
481  if (NULL != ci->oh)
482  {
484  ci->oh = NULL;
485  }
486  GNUNET_free (ci);
487  return GNUNET_YES;
488 }
489 
490 
499 static void
501  const struct GNUNET_MessageHeader *h)
502 {
503  int bucket;
504  struct GNUNET_HashCode pid_hash;
505  struct ConnectInfo *ci;
506  uint32_t strength;
507 
508  GNUNET_CRYPTO_hash (pid,
509  sizeof(struct GNUNET_PeerIdentity),
510  &pid_hash);
511  bucket = find_bucket (&pid_hash);
512  if (bucket < 0)
513  return; /* self? */
514  ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
515  pid);
516 
517  if (k_buckets[bucket].peers_size < bucket_size)
518  strength = (bucket_size - k_buckets[bucket].peers_size) * bucket;
519  else
520  strength = bucket; /* minimum value of connectivity */
521  if (GNUNET_YES ==
522  GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
523  pid))
524  strength *= 2; /* double for connected peers */
525  else if (k_buckets[bucket].peers_size > bucket_size)
526  strength = 0; /* bucket full, we really do not care about more */
527 
528  if ((0 == strength) &&
529  (NULL != ci))
530  {
531  /* release request */
533  free_connect_info (NULL,
534  pid,
535  ci));
536  return;
537  }
538  if (NULL == ci)
539  {
540  ci = GNUNET_new (struct ConnectInfo);
542  GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
543  pid,
544  ci,
546  }
547  if ((NULL != ci->oh) &&
548  (NULL != h))
550  if (NULL != h)
552  h,
554  ci);
555  if ((NULL != ci->sh) &&
556  (ci->strength != strength))
558  if (ci->strength != strength)
559  ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch,
560  pid,
561  strength);
562  ci->strength = strength;
563 }
564 
565 
578 static int
580  const struct GNUNET_PeerIdentity *pid,
581  void *value)
582 {
583  (void) cls;
584  (void) value;
585  try_connect (pid,
586  NULL);
587  return GNUNET_YES;
588 }
589 
590 
597 static void
599 {
600  GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
602  NULL);
603 }
604 
605 
615 static int
617  const struct GNUNET_PeerIdentity *key,
618  void *value)
619 {
620  struct GNUNET_BLOCK_Group *bg = cls;
621  struct GNUNET_HashCode key_hash;
622 
623  (void) cls;
624  (void) value;
625  GNUNET_CRYPTO_hash (key,
626  sizeof(struct GNUNET_PeerIdentity),
627  &key_hash);
629  &key_hash,
630  1);
632  "Adding known peer (%s) to bloomfilter for FIND PEER\n",
633  GNUNET_i2s (key));
634  return GNUNET_YES;
635 }
636 
637 
645 static void
647 {
648  struct GNUNET_TIME_Relative next_send_time;
649  struct GNUNET_BLOCK_Group *bg;
650  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
651 
652  (void) cls;
653  find_peer_task = NULL;
655  {
656  /* If we are finding many peers already, no need to send out our request right now! */
657  find_peer_task =
660  NULL);
661  newly_found_peers = 0;
662  return;
663  }
668  UINT32_MAX),
669  NULL,
670  0,
671  "filter-size",
673  NULL);
674  GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers,
676  bg);
678  gettext_noop ("# FIND PEER messages initiated"),
679  1,
680  GNUNET_NO);
681  peer_bf
685  // 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 
891 static uint64_t
892 get_distance (const struct GNUNET_HashCode *target,
893  const struct GNUNET_HashCode *have,
894  unsigned int bucket)
895 {
896  uint64_t lsb = 0;
897 
898  for (unsigned int i = bucket + 1;
899  (i < sizeof(struct GNUNET_HashCode) * 8) &&
900  (i < bucket + 1 + 64);
901  i++)
902  {
903  if (GNUNET_CRYPTO_hash_get_bit_rtl (target, i) !=
905  lsb |= (1LLU << (bucket + 64 - i)); /* first bit set will be 1,
906  * last bit set will be 63 -- if
907  * i does not reach 512 first... */
908  }
909  return lsb;
910 }
911 
912 
923 int
925  const struct GNUNET_CONTAINER_BloomFilter *bloom)
926 {
927  int bits;
928  int other_bits;
929  int bucket_num;
930  struct PeerInfo *pos;
931 
932  if (0 == GNUNET_memcmp (&my_identity_hash,
933  key))
934  return GNUNET_YES;
935  bucket_num = find_bucket (key);
936  GNUNET_assert (bucket_num >= 0);
938  key);
939  pos = k_buckets[bucket_num].head;
940  while (NULL != pos)
941  {
942  if ((NULL != bloom) &&
943  (GNUNET_YES ==
945  &pos->phash)))
946  {
947  pos = pos->next;
948  continue; /* Skip already checked entries */
949  }
950  other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->phash,
951  key);
952  if (other_bits > bits)
953  return GNUNET_NO;
954  if (other_bits == bits) /* We match the same number of bits */
955  return GNUNET_YES;
956  pos = pos->next;
957  }
958  /* No peers closer, we are the closest! */
959  return GNUNET_YES;
960 }
961 
962 
980 static struct PeerInfo *
981 select_peer (const struct GNUNET_HashCode *key,
982  const struct GNUNET_CONTAINER_BloomFilter *bloom,
983  uint32_t hops)
984 {
985  unsigned int bc;
986  unsigned int count;
987  unsigned int selected;
988  struct PeerInfo *pos;
989  struct PeerInfo *chosen;
990 
991  if (hops >= GDS_NSE_get ())
992  {
993  /* greedy selection (closest peer that is not in bloomfilter) */
994  unsigned int best_bucket = 0;
995  uint64_t best_in_bucket = UINT64_MAX;
996 
997  chosen = NULL;
998  for (bc = 0; bc <= closest_bucket; bc++)
999  {
1000  count = 0;
1001  for (pos = k_buckets[bc].head;
1002  (pos != NULL) &&
1003  (count < bucket_size);
1004  pos = pos->next)
1005  {
1006  unsigned int bucket;
1007  uint64_t dist;
1008 
1009  bucket = GNUNET_CRYPTO_hash_matching_bits (key,
1010  &pos->phash);
1011  dist = get_distance (key,
1012  &pos->phash,
1013  bucket);
1014  if (bucket < best_bucket)
1015  continue;
1016  if (dist > best_in_bucket)
1017  continue;
1018  best_bucket = bucket;
1019  best_in_bucket = dist;
1020  if ( (NULL == bloom) ||
1021  (GNUNET_NO ==
1023  &pos->phash)) )
1024  {
1025  chosen = pos;
1026  }
1027  else
1028  {
1030  "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1031  GNUNET_i2s (pos->id),
1032  GNUNET_h2s (key));
1034  gettext_noop (
1035  "# Peers excluded from routing due to Bloomfilter"),
1036  1,
1037  GNUNET_NO);
1038  chosen = NULL;
1039  }
1040  count++;
1041  }
1042  }
1043  if (NULL == chosen)
1045  gettext_noop ("# Peer selection failed"),
1046  1,
1047  GNUNET_NO);
1048  else
1050  "Selected peer `%s' in greedy routing for %s\n",
1051  GNUNET_i2s (chosen->id),
1052  GNUNET_h2s (key));
1053  return chosen;
1054  }
1055 
1056  /* select "random" peer */
1057  /* count number of peers that are available and not filtered */
1058  count = 0;
1059  for (bc = 0; bc <= closest_bucket; bc++)
1060  {
1061  pos = k_buckets[bc].head;
1062  while ((NULL != pos) && (count < bucket_size))
1063  {
1064  if ((NULL != bloom) &&
1065  (GNUNET_YES ==
1067  &pos->phash)))
1068  {
1070  gettext_noop
1071  (
1072  "# Peers excluded from routing due to Bloomfilter"),
1073  1, GNUNET_NO);
1075  "Excluded peer `%s' due to BF match in random routing for %s\n",
1076  GNUNET_i2s (pos->id),
1077  GNUNET_h2s (key));
1078  pos = pos->next;
1079  continue; /* Ignore bloomfiltered peers */
1080  }
1081  count++;
1082  pos = pos->next;
1083  }
1084  }
1085  if (0 == count) /* No peers to select from! */
1086  {
1088  gettext_noop ("# Peer selection failed"), 1,
1089  GNUNET_NO);
1090  return NULL;
1091  }
1092  /* Now actually choose a peer */
1094  count);
1095  count = 0;
1096  for (bc = 0; bc <= closest_bucket; bc++)
1097  {
1098  for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size));
1099  pos = pos->next)
1100  {
1101  if ((bloom != NULL) &&
1102  (GNUNET_YES ==
1104  &pos->phash)))
1105  {
1106  continue; /* Ignore bloomfiltered peers */
1107  }
1108  if (0 == selected--)
1109  {
1111  "Selected peer `%s' in random routing for %s\n",
1112  GNUNET_i2s (pos->id),
1113  GNUNET_h2s (key));
1114  return pos;
1115  }
1116  }
1117  }
1118  GNUNET_break (0);
1119  return NULL;
1120 }
1121 
1122 
1136 static unsigned int
1138  struct GNUNET_CONTAINER_BloomFilter *bloom,
1139  uint32_t hop_count,
1140  uint32_t target_replication,
1141  struct PeerInfo ***targets)
1142 {
1143  unsigned int ret;
1144  unsigned int off;
1145  struct PeerInfo **rtargets;
1146  struct PeerInfo *nxt;
1147 
1148  GNUNET_assert (NULL != bloom);
1149  ret = get_forward_count (hop_count,
1150  target_replication);
1151  if (0 == ret)
1152  {
1153  *targets = NULL;
1154  return 0;
1155  }
1156  rtargets = GNUNET_new_array (ret,
1157  struct PeerInfo *);
1158  for (off = 0; off < ret; off++)
1159  {
1160  nxt = select_peer (key,
1161  bloom,
1162  hop_count);
1163  if (NULL == nxt)
1164  break;
1165  rtargets[off] = nxt;
1168  &nxt->phash));
1170  &nxt->phash);
1171  }
1173  "Selected %u/%u peers at hop %u for %s (target was %u)\n",
1174  off,
1175  GNUNET_CONTAINER_multipeermap_size (all_connected_peers),
1176  (unsigned int) hop_count,
1177  GNUNET_h2s (key),
1178  ret);
1179  if (0 == off)
1180  {
1181  GNUNET_free (rtargets);
1182  *targets = NULL;
1183  return 0;
1184  }
1185  *targets = rtargets;
1187  "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1188  GNUNET_h2s (key),
1189  off,
1190  ret);
1191  return off;
1192 }
1193 
1194 
1215 int
1218  uint32_t desired_replication_level,
1220  uint32_t hop_count,
1221  struct GNUNET_CONTAINER_BloomFilter *bf,
1222  const struct GNUNET_HashCode *key,
1223  unsigned int put_path_length,
1224  struct GNUNET_PeerIdentity *put_path,
1225  const void *data,
1226  size_t data_size)
1227 {
1228  unsigned int target_count;
1229  unsigned int i;
1230  struct PeerInfo **targets;
1231  struct PeerInfo *target;
1232  size_t msize;
1233  struct GNUNET_MQ_Envelope *env;
1234  struct PeerPutMessage *ppm;
1235  struct GNUNET_PeerIdentity *pp;
1236  unsigned int skip_count;
1237 
1238  GNUNET_assert (NULL != bf);
1240  "Adding myself (%s) to PUT bloomfilter for %s\n",
1242  GNUNET_h2s (key));
1244  &my_identity_hash);
1246  gettext_noop ("# PUT requests routed"),
1247  1,
1248  GNUNET_NO);
1249  target_count
1250  = get_target_peers (key,
1251  bf,
1252  hop_count,
1253  desired_replication_level,
1254  &targets);
1255  if (0 == target_count)
1256  {
1258  "Routing PUT for %s terminates after %u hops at %s\n",
1259  GNUNET_h2s (key),
1260  (unsigned int) hop_count,
1261  GNUNET_i2s (&my_identity));
1262  return GNUNET_NO;
1263  }
1264  msize = put_path_length * sizeof(struct GNUNET_PeerIdentity) + data_size;
1265  if (msize + sizeof(struct PeerPutMessage)
1267  {
1268  put_path_length = 0;
1269  msize = data_size;
1270  }
1271  if (msize + sizeof(struct PeerPutMessage)
1273  {
1274  GNUNET_break (0);
1275  GNUNET_free (targets);
1276  return GNUNET_NO;
1277  }
1279  gettext_noop (
1280  "# PUT messages queued for transmission"),
1281  target_count,
1282  GNUNET_NO);
1283  skip_count = 0;
1284  for (i = 0; i < target_count; i++)
1285  {
1286  target = targets[i];
1288  {
1289  /* skip */
1291  gettext_noop (
1292  "# P2P messages dropped due to full queue"),
1293  1,
1294  GNUNET_NO);
1295  skip_count++;
1296  continue;
1297  }
1299  "Routing PUT for %s after %u hops to %s\n",
1300  GNUNET_h2s (key),
1301  (unsigned int) hop_count,
1302  GNUNET_i2s (target->id));
1303  env = GNUNET_MQ_msg_extra (ppm,
1304  msize,
1306  ppm->options = htonl (options);
1307  ppm->type = htonl (type);
1308  ppm->hop_count = htonl (hop_count + 1);
1309  ppm->desired_replication_level = htonl (desired_replication_level);
1310  ppm->put_path_length = htonl (put_path_length);
1311  ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1314  &target->phash));
1317  ppm->bloomfilter,
1318  DHT_BLOOM_SIZE));
1319  ppm->key = *key;
1320  pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1321  GNUNET_memcpy (pp,
1322  put_path,
1323  sizeof(struct GNUNET_PeerIdentity) * put_path_length);
1324  GNUNET_memcpy (&pp[put_path_length],
1325  data,
1326  data_size);
1327  GNUNET_MQ_send (target->mq,
1328  env);
1329  }
1330  GNUNET_free (targets);
1331  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1332 }
1333 
1334 
1352 int
1355  uint32_t desired_replication_level,
1356  uint32_t hop_count,
1357  const struct GNUNET_HashCode *key,
1358  const void *xquery,
1359  size_t xquery_size,
1360  struct GNUNET_BLOCK_Group *bg,
1361  struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1362 {
1363  unsigned int target_count;
1364  struct PeerInfo **targets;
1365  struct PeerInfo *target;
1366  struct GNUNET_MQ_Envelope *env;
1367  size_t msize;
1368  struct PeerGetMessage *pgm;
1369  char *xq;
1370  size_t reply_bf_size;
1371  void *reply_bf;
1372  unsigned int skip_count;
1373  uint32_t bf_nonce;
1374 
1375  GNUNET_assert (NULL != peer_bf);
1377  gettext_noop ("# GET requests routed"),
1378  1,
1379  GNUNET_NO);
1380  target_count = get_target_peers (key,
1381  peer_bf,
1382  hop_count,
1383  desired_replication_level,
1384  &targets);
1386  "Adding myself (%s) to GET bloomfilter for %s\n",
1388  GNUNET_h2s (key));
1390  &my_identity_hash);
1391  if (0 == target_count)
1392  {
1394  "Routing GET for %s terminates after %u hops at %s\n",
1395  GNUNET_h2s (key),
1396  (unsigned int) hop_count,
1397  GNUNET_i2s (&my_identity));
1398  return GNUNET_NO;
1399  }
1400  if (GNUNET_OK !=
1402  &bf_nonce,
1403  &reply_bf,
1404  &reply_bf_size))
1405  {
1406  reply_bf = NULL;
1407  reply_bf_size = 0;
1409  UINT32_MAX);
1410  }
1411  msize = xquery_size + reply_bf_size;
1412  if (msize + sizeof(struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
1413  {
1414  GNUNET_break (0);
1415  GNUNET_free (reply_bf);
1416  GNUNET_free (targets);
1417  return GNUNET_NO;
1418  }
1420  gettext_noop (
1421  "# GET messages queued for transmission"),
1422  target_count,
1423  GNUNET_NO);
1424  /* forward request */
1425  skip_count = 0;
1426  for (unsigned int i = 0; i < target_count; i++)
1427  {
1428  target = targets[i];
1430  {
1431  /* skip */
1433  gettext_noop (
1434  "# P2P messages dropped due to full queue"),
1435  1, GNUNET_NO);
1436  skip_count++;
1437  continue;
1438  }
1440  "Routing GET for %s after %u hops to %s\n",
1441  GNUNET_h2s (key),
1442  (unsigned int) hop_count,
1443  GNUNET_i2s (target->id));
1444  env = GNUNET_MQ_msg_extra (pgm,
1445  msize,
1447  pgm->options = htonl (options);
1448  pgm->type = htonl (type);
1449  pgm->hop_count = htonl (hop_count + 1);
1450  pgm->desired_replication_level = htonl (desired_replication_level);
1451  pgm->xquery_size = htonl (xquery_size);
1452  pgm->bf_mutator = bf_nonce;
1455  &target->phash));
1458  pgm->bloomfilter,
1459  DHT_BLOOM_SIZE));
1460  pgm->key = *key;
1461  xq = (char *) &pgm[1];
1462  GNUNET_memcpy (xq,
1463  xquery,
1464  xquery_size);
1465  GNUNET_memcpy (&xq[xquery_size],
1466  reply_bf,
1467  reply_bf_size);
1468  GNUNET_MQ_send (target->mq,
1469  env);
1470  }
1471  GNUNET_free (targets);
1472  GNUNET_free (reply_bf);
1473  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1474 }
1475 
1476 
1493 void
1495  enum GNUNET_BLOCK_Type type,
1497  const struct GNUNET_HashCode *key,
1498  unsigned int put_path_length,
1499  const struct GNUNET_PeerIdentity *put_path,
1500  unsigned int get_path_length,
1501  const struct GNUNET_PeerIdentity *get_path,
1502  const void *data,
1503  size_t data_size)
1504 {
1505  struct PeerInfo *pi;
1506  struct GNUNET_MQ_Envelope *env;
1507  size_t msize;
1508  struct PeerResultMessage *prm;
1509  struct GNUNET_PeerIdentity *paths;
1510 
1511  msize = data_size + (get_path_length + put_path_length)
1512  * sizeof(struct GNUNET_PeerIdentity);
1513  if ((msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
1514  (get_path_length >
1515  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1516  (put_path_length >
1517  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1518  (data_size > GNUNET_MAX_MESSAGE_SIZE))
1519  {
1520  GNUNET_break (0);
1521  return;
1522  }
1523  pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
1524  target);
1525  if (NULL == pi)
1526  {
1527  /* peer disconnected in the meantime, drop reply */
1529  "No matching peer for reply for key %s\n",
1530  GNUNET_h2s (key));
1531  return;
1532  }
1534  {
1535  /* skip */
1537  gettext_noop (
1538  "# P2P messages dropped due to full queue"),
1539  1,
1540  GNUNET_NO);
1542  "Peer queue full, ignoring reply for key %s\n",
1543  GNUNET_h2s (key));
1544  return;
1545  }
1546 
1548  "Forwarding reply for key %s to peer %s\n",
1549  GNUNET_h2s (key),
1550  GNUNET_i2s (target));
1552  gettext_noop
1553  ("# RESULT messages queued for transmission"), 1,
1554  GNUNET_NO);
1555  env = GNUNET_MQ_msg_extra (prm,
1556  msize,
1558  prm->type = htonl (type);
1559  prm->put_path_length = htonl (put_path_length);
1560  prm->get_path_length = htonl (get_path_length);
1561  prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1562  prm->key = *key;
1563  paths = (struct GNUNET_PeerIdentity *) &prm[1];
1564  GNUNET_memcpy (paths,
1565  put_path,
1566  put_path_length * sizeof(struct GNUNET_PeerIdentity));
1567  GNUNET_memcpy (&paths[put_path_length],
1568  get_path,
1569  get_path_length * sizeof(struct GNUNET_PeerIdentity));
1570  GNUNET_memcpy (&paths[put_path_length + get_path_length],
1571  data,
1572  data_size);
1573  GNUNET_MQ_send (pi->mq,
1574  env);
1575 }
1576 
1577 
1584 static void
1585 core_init (void *cls,
1586  const struct GNUNET_PeerIdentity *identity)
1587 {
1588  (void) cls;
1590  "CORE called, I am %s\n",
1591  GNUNET_i2s (identity));
1592  my_identity = *identity;
1593  GNUNET_CRYPTO_hash (identity,
1594  sizeof(struct GNUNET_PeerIdentity),
1595  &my_identity_hash);
1597 }
1598 
1599 
1607 static int
1609  const struct PeerPutMessage *put)
1610 {
1611  uint32_t putlen;
1612  uint16_t msize;
1613 
1614  (void) cls;
1615  msize = ntohs (put->header.size);
1616  putlen = ntohl (put->put_path_length);
1617  if ((msize <
1618  sizeof(struct PeerPutMessage)
1619  + putlen * sizeof(struct GNUNET_PeerIdentity)) ||
1620  (putlen >
1621  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
1622  {
1623  GNUNET_break_op (0);
1624  return GNUNET_SYSERR;
1625  }
1626  return GNUNET_OK;
1627 }
1628 
1629 
1636 static void
1638  const struct PeerPutMessage *put)
1639 {
1640  struct PeerInfo *peer = cls;
1641  const struct GNUNET_PeerIdentity *put_path;
1642  const void *payload;
1643  uint32_t putlen;
1644  uint16_t msize;
1645  size_t payload_size;
1647  struct GNUNET_CONTAINER_BloomFilter *bf;
1648  struct GNUNET_HashCode test_key;
1649  int forwarded;
1650  struct GNUNET_TIME_Absolute exp_time;
1651 
1652  exp_time = GNUNET_TIME_absolute_ntoh (put->expiration_time);
1653  if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
1654  {
1656  gettext_noop ("# Expired PUTs discarded"),
1657  1,
1658  GNUNET_NO);
1659  return;
1660  }
1661  msize = ntohs (put->header.size);
1662  putlen = ntohl (put->put_path_length);
1664  gettext_noop ("# P2P PUT requests received"),
1665  1,
1666  GNUNET_NO);
1668  gettext_noop ("# P2P PUT bytes received"),
1669  msize,
1670  GNUNET_NO);
1671  put_path = (const struct GNUNET_PeerIdentity *) &put[1];
1672  payload = &put_path[putlen];
1673  options = ntohl (put->options);
1674  payload_size = msize - (sizeof(struct PeerPutMessage)
1675  + putlen * sizeof(struct GNUNET_PeerIdentity));
1676 
1678  "PUT for `%s' from %s\n",
1679  GNUNET_h2s (&put->key),
1680  GNUNET_i2s (peer->id));
1682  {
1683  char *tmp;
1684  char *pp;
1685 
1686  pp = GNUNET_STRINGS_pp2s (put_path,
1687  putlen);
1690  "R5N PUT %s: %s->%s (%u, %u=>%u, PP: %s)\n",
1691  GNUNET_h2s (&put->key),
1692  GNUNET_i2s (peer->id),
1693  tmp,
1694  ntohl (put->hop_count),
1696  &put->key),
1698  &put->key),
1699  pp);
1700  GNUNET_free (pp);
1701  GNUNET_free (tmp);
1702  }
1703  switch (GNUNET_BLOCK_get_key
1705  ntohl (put->type),
1706  payload,
1707  payload_size,
1708  &test_key))
1709  {
1710  case GNUNET_YES:
1711  if (0 != memcmp (&test_key,
1712  &put->key,
1713  sizeof(struct GNUNET_HashCode)))
1714  {
1715  char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
1716 
1717  GNUNET_break_op (0);
1719  "PUT with key `%s' for block with key %s\n",
1720  put_s,
1721  GNUNET_h2s_full (&test_key));
1722  GNUNET_free (put_s);
1723  return;
1724  }
1725  break;
1726 
1727  case GNUNET_NO:
1728  GNUNET_break_op (0);
1729  return;
1730 
1731  case GNUNET_SYSERR:
1732  /* cannot verify, good luck */
1733  break;
1734  }
1735  if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
1736  {
1738  ntohl (put->type),
1739  NULL, /* query group */
1741  NULL, /* query */
1742  NULL, 0, /* xquery */
1743  payload,
1744  payload_size))
1745  {
1748  break;
1749 
1756  default:
1757  GNUNET_break_op (0);
1758  return;
1759  }
1760  }
1761 
1767  &peer->phash));
1768  {
1769  struct GNUNET_PeerIdentity pp[putlen + 1];
1770 
1771  /* extend 'put path' by sender */
1772  if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1773  {
1774 #if SANITY_CHECKS
1775  for (unsigned int i = 0; i <= putlen; i++)
1776  {
1777  for (unsigned int j = 0; j < i; j++)
1778  {
1779  GNUNET_break (0 != memcmp (&pp[i],
1780  &pp[j],
1781  sizeof(struct GNUNET_PeerIdentity)));
1782  }
1783  GNUNET_break (0 != memcmp (&pp[i],
1784  peer->id,
1785  sizeof(struct GNUNET_PeerIdentity)));
1786  }
1787 #endif
1788  GNUNET_memcpy (pp,
1789  put_path,
1790  putlen * sizeof(struct GNUNET_PeerIdentity));
1791  pp[putlen] = *peer->id;
1792  putlen++;
1793  }
1794  else
1795  putlen = 0;
1796 
1797  /* give to local clients */
1798  GDS_CLIENTS_handle_reply (exp_time,
1799  &put->key,
1800  0,
1801  NULL,
1802  putlen,
1803  pp,
1804  ntohl (put->type),
1805  payload_size,
1806  payload);
1807  /* store locally */
1808  if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1809  (GDS_am_closest_peer (&put->key, bf)))
1810  GDS_DATACACHE_handle_put (exp_time,
1811  &put->key,
1812  putlen,
1813  pp,
1814  ntohl (put->type),
1815  payload_size,
1816  payload);
1817  /* route to other peers */
1818  forwarded = GDS_NEIGHBOURS_handle_put (ntohl (put->type),
1819  options,
1820  ntohl (
1822  exp_time,
1823  ntohl (put->hop_count),
1824  bf,
1825  &put->key,
1826  putlen,
1827  pp,
1828  payload,
1829  payload_size);
1830  /* notify monitoring clients */
1831  GDS_CLIENTS_process_put (options
1832  | ((GNUNET_OK == forwarded)
1834  : 0),
1835  ntohl (put->type),
1836  ntohl (put->hop_count),
1837  ntohl (put->desired_replication_level),
1838  putlen, pp,
1839  exp_time,
1840  &put->key,
1841  payload,
1842  payload_size);
1843  }
1845 }
1846 
1847 
1856 static void
1858  const struct GNUNET_HashCode *key,
1859  struct GNUNET_BLOCK_Group *bg)
1860 {
1861  int bucket_idx;
1862  struct PeerBucket *bucket;
1863  struct PeerInfo *peer;
1864  unsigned int choice;
1865  const struct GNUNET_HELLO_Message *hello;
1866  size_t hello_size;
1867 
1868  /* first, check about our own HELLO */
1869  if (NULL != GDS_my_hello)
1870  {
1871  hello_size = GNUNET_HELLO_size ((const struct
1873  GNUNET_break (hello_size >= sizeof(struct GNUNET_MessageHeader));
1877  bg,
1880  NULL, 0,
1881  GDS_my_hello,
1882  hello_size))
1883  {
1888  key,
1889  0,
1890  NULL,
1891  0,
1892  NULL,
1893  GDS_my_hello,
1894  hello_size);
1895  }
1896  else
1897  {
1899  gettext_noop (
1900  "# FIND PEER requests ignored due to Bloomfilter"),
1901  1,
1902  GNUNET_NO);
1903  }
1904  }
1905  else
1906  {
1908  gettext_noop (
1909  "# FIND PEER requests ignored due to lack of HELLO"),
1910  1,
1911  GNUNET_NO);
1912  }
1913 
1914  /* then, also consider sending a random HELLO from the closest bucket */
1915  if (0 == memcmp (&my_identity_hash,
1916  key,
1917  sizeof(struct GNUNET_HashCode)))
1918  bucket_idx = closest_bucket;
1919  else
1920  bucket_idx = GNUNET_MIN ((int) closest_bucket,
1921  find_bucket (key));
1922  if (bucket_idx < 0)
1923  return;
1924  bucket = &k_buckets[bucket_idx];
1925  if (bucket->peers_size == 0)
1926  return;
1928  bucket->peers_size);
1929  peer = bucket->head;
1930  while (choice > 0)
1931  {
1932  GNUNET_assert (NULL != peer);
1933  peer = peer->next;
1934  choice--;
1935  }
1936  choice = bucket->peers_size;
1937  do
1938  {
1939  peer = peer->next;
1940  if (0 == choice--)
1941  return; /* no non-masked peer available */
1942  if (NULL == peer)
1943  peer = bucket->head;
1944  hello = GDS_HELLO_get (peer->id);
1945  }
1946  while ((NULL == hello) ||
1950  bg,
1952  &peer->phash,
1953  NULL, 0,
1954  hello,
1955  (hello_size = GNUNET_HELLO_size (hello)))));
1960  key,
1961  0,
1962  NULL,
1963  0,
1964  NULL,
1965  hello,
1966  hello_size);
1967 }
1968 
1969 
1984 static void
1986  enum GNUNET_BLOCK_Type type,
1988  const struct GNUNET_HashCode *key,
1989  unsigned int put_path_length,
1990  const struct GNUNET_PeerIdentity *put_path,
1991  unsigned int get_path_length,
1992  const struct GNUNET_PeerIdentity *get_path,
1993  const void *data,
1994  size_t data_size)
1995 {
1996  struct PeerInfo *peer = cls;
1997  char *pp;
1998 
1999  pp = GNUNET_STRINGS_pp2s (put_path,
2000  put_path_length);
2002  "Found local result for %s (PP: %s)\n",
2003  GNUNET_h2s (key),
2004  pp);
2005  GNUNET_free (pp);
2007  type,
2008  expiration_time,
2009  key,
2010  put_path_length, put_path,
2011  get_path_length, get_path,
2012  data, data_size);
2013 }
2014 
2015 
2023 static int
2025  const struct PeerGetMessage *get)
2026 {
2027  uint32_t xquery_size;
2028  uint16_t msize;
2029 
2030  (void) cls;
2031  msize = ntohs (get->header.size);
2032  xquery_size = ntohl (get->xquery_size);
2033  if (msize < sizeof(struct PeerGetMessage) + xquery_size)
2034  {
2035  GNUNET_break_op (0);
2036  return GNUNET_SYSERR;
2037  }
2038  return GNUNET_OK;
2039 }
2040 
2041 
2048 static void
2050  const struct PeerGetMessage *get)
2051 {
2052  struct PeerInfo *peer = cls;
2053  uint32_t xquery_size;
2054  size_t reply_bf_size;
2055  uint16_t msize;
2056  enum GNUNET_BLOCK_Type type;
2059  struct GNUNET_BLOCK_Group *bg;
2060  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2061  const char *xquery;
2062  int forwarded;
2063 
2064  /* parse and validate message */
2065  msize = ntohs (get->header.size);
2066  xquery_size = ntohl (get->xquery_size);
2067  reply_bf_size = msize - (sizeof(struct PeerGetMessage) + xquery_size);
2068  type = ntohl (get->type);
2069  options = ntohl (get->options);
2070  xquery = (const char *) &get[1];
2072  gettext_noop ("# P2P GET requests received"),
2073  1,
2074  GNUNET_NO);
2076  gettext_noop ("# P2P GET bytes received"),
2077  msize,
2078  GNUNET_NO);
2080  {
2081  char *tmp;
2082 
2085  "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
2086  GNUNET_h2s (&get->key),
2087  GNUNET_i2s (peer->id),
2088  tmp,
2089  ntohl (get->hop_count),
2091  &get->key),
2093  &get->key),
2094  ntohl (get->xquery_size),
2095  xquery);
2096  GNUNET_free (tmp);
2097  }
2098  eval
2100  type,
2101  NULL,
2103  &get->key,
2104  xquery,
2105  xquery_size,
2106  NULL,
2107  0);
2109  {
2110  /* request invalid or block type not supported */
2112  return;
2113  }
2114  peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
2119  &peer->phash));
2121  type,
2122  get->bf_mutator,
2123  &xquery[xquery_size],
2124  reply_bf_size,
2125  "filter-size",
2126  reply_bf_size,
2127  NULL);
2129  "GET for %s at %s after %u hops\n",
2130  GNUNET_h2s (&get->key),
2132  (unsigned int) ntohl (get->hop_count));
2133  /* local lookup (this may update the reply_bf) */
2134  if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2135  (GDS_am_closest_peer (&get->key,
2136  peer_bf)))
2137  {
2138  if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
2139  {
2141  gettext_noop (
2142  "# P2P FIND PEER requests processed"),
2143  1,
2144  GNUNET_NO);
2145  handle_find_peer (peer->id,
2146  &get->key,
2147  bg);
2148  }
2149  else
2150  {
2151  eval = GDS_DATACACHE_handle_get (&get->key,
2152  type,
2153  xquery,
2154  xquery_size,
2155  bg,
2157  peer);
2158  }
2159  }
2160  else
2161  {
2163  gettext_noop ("# P2P GET requests ONLY routed"),
2164  1,
2165  GNUNET_NO);
2166  }
2167 
2168  /* remember request for routing replies */
2169  GDS_ROUTING_add (peer->id,
2170  type,
2171  bg, /* bg now owned by routing, but valid at least until end of this function! */
2172  options,
2173  &get->key,
2174  xquery,
2175  xquery_size);
2176 
2177  /* P2P forwarding */
2178  forwarded = GNUNET_NO;
2179  if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
2180  forwarded = GDS_NEIGHBOURS_handle_get (type,
2181  options,
2182  ntohl (
2183  get->desired_replication_level),
2184  ntohl (get->hop_count),
2185  &get->key,
2186  xquery,
2187  xquery_size,
2188  bg,
2189  peer_bf);
2190  GDS_CLIENTS_process_get (options
2191  | ((GNUNET_OK == forwarded)
2192  ? GNUNET_DHT_RO_LAST_HOP : 0),
2193  type,
2194  ntohl (get->hop_count),
2195  ntohl (get->desired_replication_level),
2196  0,
2197  NULL,
2198  &get->key);
2199 
2200  /* clean up; note that 'bg' is owned by routing now! */
2202 }
2203 
2204 
2212 static int
2214  const struct PeerResultMessage *prm)
2215 {
2216  uint32_t get_path_length;
2217  uint32_t put_path_length;
2218  uint16_t msize;
2219 
2220  (void) cls;
2221  msize = ntohs (prm->header.size);
2222  put_path_length = ntohl (prm->put_path_length);
2223  get_path_length = ntohl (prm->get_path_length);
2224  if ((msize <
2225  sizeof(struct PeerResultMessage) + (get_path_length
2226  + put_path_length)
2227  * sizeof(struct GNUNET_PeerIdentity)) ||
2228  (get_path_length >
2229  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
2230  (put_path_length >
2231  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
2232  {
2233  GNUNET_break_op (0);
2234  return GNUNET_SYSERR;
2235  }
2236  return GNUNET_OK;
2237 }
2238 
2239 
2253 static void
2255  const struct GNUNET_HashCode *key,
2256  unsigned int get_path_length,
2257  const struct GNUNET_PeerIdentity *get_path,
2258  unsigned int put_path_length,
2259  const struct GNUNET_PeerIdentity *put_path,
2260  enum GNUNET_BLOCK_Type type,
2261  size_t data_size,
2262  const void *data)
2263 {
2264  /* forward to local clients */
2265  GDS_CLIENTS_handle_reply (expiration_time,
2266  key,
2267  get_path_length,
2268  get_path,
2269  put_path_length,
2270  put_path,
2271  type,
2272  data_size,
2273  data);
2275  get_path,
2276  get_path_length,
2277  put_path,
2278  put_path_length,
2279  expiration_time,
2280  key,
2281  data,
2282  data_size);
2283  if (GNUNET_YES == cache_results)
2284  {
2285  struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length];
2286 
2287  GNUNET_memcpy (xput_path,
2288  put_path,
2289  put_path_length * sizeof(struct GNUNET_PeerIdentity));
2290  GNUNET_memcpy (&xput_path[put_path_length],
2291  get_path,
2292  get_path_length * sizeof(struct GNUNET_PeerIdentity));
2293 
2294  GDS_DATACACHE_handle_put (expiration_time,
2295  key,
2296  get_path_length + put_path_length,
2297  xput_path,
2298  type,
2299  data_size,
2300  data);
2301  }
2302  /* forward to other peers */
2303  GDS_ROUTING_process (type,
2304  expiration_time,
2305  key,
2306  put_path_length,
2307  put_path,
2308  get_path_length,
2309  get_path,
2310  data,
2311  data_size);
2312 }
2313 
2314 
2321 static void
2323  const struct PeerResultMessage *prm)
2324 {
2325  struct PeerInfo *peer = cls;
2326  const struct GNUNET_PeerIdentity *put_path;
2327  const struct GNUNET_PeerIdentity *get_path;
2328  const void *data;
2329  uint32_t get_path_length;
2330  uint32_t put_path_length;
2331  uint16_t msize;
2332  size_t data_size;
2333  enum GNUNET_BLOCK_Type type;
2334  struct GNUNET_TIME_Absolute exp_time;
2335 
2336  /* parse and validate message */
2337  exp_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time);
2338  if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
2339  {
2341  gettext_noop ("# Expired results discarded"),
2342  1,
2343  GNUNET_NO);
2344  return;
2345  }
2346  msize = ntohs (prm->header.size);
2347  put_path_length = ntohl (prm->put_path_length);
2348  get_path_length = ntohl (prm->get_path_length);
2349  put_path = (const struct GNUNET_PeerIdentity *) &prm[1];
2350  get_path = &put_path[put_path_length];
2351  type = ntohl (prm->type);
2352  data = (const void *) &get_path[get_path_length];
2353  data_size = msize - (sizeof(struct PeerResultMessage)
2354  + (get_path_length
2355  + put_path_length) * sizeof(struct
2358  gettext_noop ("# P2P RESULTS received"),
2359  1,
2360  GNUNET_NO);
2362  gettext_noop ("# P2P RESULT bytes received"),
2363  msize,
2364  GNUNET_NO);
2366  {
2367  char *tmp;
2368  char *pp;
2369  char *gp;
2370 
2371  gp = GNUNET_STRINGS_pp2s (get_path,
2372  get_path_length);
2373  pp = GNUNET_STRINGS_pp2s (put_path,
2374  put_path_length);
2377  "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n",
2378  GNUNET_h2s (&prm->key),
2379  GNUNET_i2s (peer->id),
2380  tmp,
2381  gp,
2382  pp);
2383  GNUNET_free (gp);
2384  GNUNET_free (pp);
2385  GNUNET_free (tmp);
2386  }
2387  /* if we got a HELLO, consider it for our own routing table */
2388  if (GNUNET_BLOCK_TYPE_DHT_HELLO == type)
2389  {
2390  const struct GNUNET_MessageHeader *h;
2391  struct GNUNET_PeerIdentity pid;
2392 
2393  /* Should be a HELLO, validate and consider using it! */
2394  if (data_size < sizeof(struct GNUNET_HELLO_Message))
2395  {
2396  GNUNET_break_op (0);
2397  return;
2398  }
2399  h = data;
2400  if (data_size != ntohs (h->size))
2401  {
2402  GNUNET_break_op (0);
2403  return;
2404  }
2405  if (GNUNET_OK !=
2406  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h,
2407  &pid))
2408  {
2409  GNUNET_break_op (0);
2410  return;
2411  }
2412  if ((GNUNET_YES != disable_try_connect) &&
2413  (0 != memcmp (&my_identity,
2414  &pid,
2415  sizeof(struct GNUNET_PeerIdentity))))
2416  try_connect (&pid,
2417  h);
2418  }
2419 
2420  /* First, check if 'peer' is already on the path, and if
2421  so, truncate it instead of expanding. */
2422  for (unsigned int i = 0; i <= get_path_length; i++)
2423  if (0 == memcmp (&get_path[i],
2424  peer->id,
2425  sizeof(struct GNUNET_PeerIdentity)))
2426  {
2427  process_reply_with_path (exp_time,
2428  &prm->key,
2429  i,
2430  get_path,
2431  put_path_length,
2432  put_path,
2433  type,
2434  data_size,
2435  data);
2436  return;
2437  }
2438 
2439  /* Need to append 'peer' to 'get_path' (normal case) */
2440  {
2441  struct GNUNET_PeerIdentity xget_path[get_path_length + 1];
2442 
2443  GNUNET_memcpy (xget_path,
2444  get_path,
2445  get_path_length * sizeof(struct GNUNET_PeerIdentity));
2446  xget_path[get_path_length] = *peer->id;
2447 
2448  process_reply_with_path (exp_time,
2449  &prm->key,
2450  get_path_length + 1,
2451  xget_path,
2452  put_path_length,
2453  put_path,
2454  type,
2455  data_size,
2456  data);
2457  }
2458 }
2459 
2460 
2466 int
2468 {
2469  struct GNUNET_MQ_MessageHandler core_handlers[] = {
2470  GNUNET_MQ_hd_var_size (dht_p2p_get,
2472  struct PeerGetMessage,
2473  NULL),
2474  GNUNET_MQ_hd_var_size (dht_p2p_put,
2476  struct PeerPutMessage,
2477  NULL),
2478  GNUNET_MQ_hd_var_size (dht_p2p_result,
2480  struct PeerResultMessage,
2481  NULL),
2483  };
2484  unsigned long long temp_config_num;
2485 
2488  "DHT",
2489  "DISABLE_TRY_CONNECT");
2490  if (GNUNET_OK ==
2492  "DHT",
2493  "bucket_size",
2494  &temp_config_num))
2495  bucket_size = (unsigned int) temp_config_num;
2498  "DHT",
2499  "CACHE_RESULTS");
2500 
2502  (NULL != getenv ("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO;
2504  core_api = GNUNET_CORE_connect (GDS_cfg,
2505  NULL,
2506  &core_init,
2509  core_handlers);
2510  if (NULL == core_api)
2511  return GNUNET_SYSERR;
2512  all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256,
2513  GNUNET_YES);
2514  all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256,
2515  GNUNET_NO);
2516  return GNUNET_OK;
2517 }
2518 
2519 
2523 void
2525 {
2526  if (NULL == core_api)
2527  return;
2528  GNUNET_CORE_disconnect (core_api);
2529  core_api = NULL;
2530  GNUNET_assert (0 ==
2531  GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
2532  GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers);
2533  all_connected_peers = NULL;
2534  GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
2536  NULL);
2537  GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers);
2538  all_desired_peers = NULL;
2540  ats_ch = NULL;
2541  GNUNET_assert (NULL == find_peer_task);
2542 }
2543 
2544 
2550 struct GNUNET_PeerIdentity *
2552 {
2553  return &my_identity;
2554 }
2555 
2556 
2557 /* 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:671
uint32_t type
Content type.
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.
static uint64_t get_distance(const struct GNUNET_HashCode *target, const struct GNUNET_HashCode *have, unsigned int bucket)
Compute the distance between have and target as a 64-bit value.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:542
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.
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:2195
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:77
int GNUNET_CRYPTO_hash_get_bit_rtl(const struct GNUNET_HashCode *code, unsigned int bit)
Obtain a bit from a hashcode.
Definition: crypto_hash.c:180
#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:189
#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:181
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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.
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.
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).
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).
#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:99
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:1269
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.
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:41
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:337
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:95
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:73
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:1296
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:93
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.
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:692
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:730
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:230
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:652
Block group data.
static struct GNUNET_ATS_ConnectivityHandle * ats_ch
Handle to ATS connectivity.
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 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:232
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.
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:355
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.
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.
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:464
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 associated with a filter in memory, flush to drive if needed (do not free the space on...
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:972
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.