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 
155  struct GNUNET_HashCode key;
156 
157  /* put path (if tracked) */
158 
159  /* Payload */
160 };
161 
162 
167 {
172 
176  uint32_t type GNUNET_PACKED;
177 
182 
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 
373 static struct PeerBucket k_buckets[MAX_BUCKETS];
374 
380 
386 
390 static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
391 
396 
400 static struct GNUNET_PeerIdentity my_identity;
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;
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 
509  sizeof(struct GNUNET_PeerIdentity),
510  &pid_hash);
511  bucket = find_bucket (&pid_hash);
512  if (bucket < 0)
513  return; /* self? */
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 ==
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);
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)
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 {
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;
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! */
660  NULL);
661  newly_found_peers = 0;
662  return;
663  }
668  UINT32_MAX),
669  NULL,
670  0,
671  "filter-size",
673  NULL);
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);
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));
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;
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));
753  k_buckets[pi->peer_bucket].tail,
754  pi);
755  k_buckets[pi->peer_bucket].peers_size++;
757  (unsigned int) pi->peer_bucket);
760  pi->id,
761  pi,
763  if ((pi->peer_bucket > 0) &&
764  (k_buckets[pi->peer_bucket].peers_size <= bucket_size))
765  {
768  }
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);
808  peer,
809  to_remove));
812  {
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
840 get_forward_count (uint32_t hop_count,
841  uint32_t target_replication)
842 {
843  uint32_t random_value;
844  uint32_t forward_count;
845  float target_value;
846 
847  if (0 == target_replication)
848  target_replication = 1; /* 0 is verboten */
849  if (target_replication > MAXIMUM_REPLICATION_LEVEL)
850  target_replication = MAXIMUM_REPLICATION_LEVEL;
851  if (hop_count > GDS_NSE_get () * 4.0)
852  {
853  /* forcefully terminate */
855  gettext_noop ("# requests TTL-dropped"),
856  1, GNUNET_NO);
857  return 0;
858  }
859  if (hop_count > GDS_NSE_get () * 2.0)
860  {
861  /* Once we have reached our ideal number of hops, only forward to 1 peer */
862  return 1;
863  }
864  /* bound by system-wide maximum */
865  target_replication =
866  GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL, target_replication);
867  target_value =
868  1 + (target_replication - 1.0) / (GDS_NSE_get ()
869  + ((float) (target_replication - 1.0)
870  * hop_count));
871 
872 
873  /* Set forward count to floor of target_value */
874  forward_count = (uint32_t) target_value;
875  /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
876  target_value = target_value - forward_count;
877  random_value =
879  if (random_value < (target_value * UINT32_MAX))
880  forward_count++;
881  return GNUNET_MIN (forward_count,
883 }
884 
885 
898 static uint64_t
899 get_distance (const struct GNUNET_HashCode *target,
900  const struct GNUNET_HashCode *have,
901  unsigned int bucket)
902 {
903  uint64_t lsb = 0;
904 
905  for (unsigned int i = bucket + 1;
906  (i < sizeof(struct GNUNET_HashCode) * 8) &&
907  (i < bucket + 1 + 64);
908  i++)
909  {
910  if (GNUNET_CRYPTO_hash_get_bit_rtl (target, i) !=
912  lsb |= (1LLU << (bucket + 64 - i)); /* first bit set will be 1,
913  * last bit set will be 63 -- if
914  * i does not reach 512 first... */
915  }
916  return lsb;
917 }
918 
919 
930 int
932  const struct GNUNET_CONTAINER_BloomFilter *bloom)
933 {
934  int bits;
935  int other_bits;
936  int bucket_num;
937  struct PeerInfo *pos;
938 
939  if (0 == GNUNET_memcmp (&my_identity_hash,
940  key))
941  return GNUNET_YES;
942  bucket_num = find_bucket (key);
943  GNUNET_assert (bucket_num >= 0);
945  key);
946  pos = k_buckets[bucket_num].head;
947  while (NULL != pos)
948  {
949  if ((NULL != bloom) &&
950  (GNUNET_YES ==
952  &pos->phash)))
953  {
954  pos = pos->next;
955  continue; /* Skip already checked entries */
956  }
957  other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->phash,
958  key);
959  if (other_bits > bits)
960  return GNUNET_NO;
961  if (other_bits == bits) /* We match the same number of bits */
962  return GNUNET_YES;
963  pos = pos->next;
964  }
965  /* No peers closer, we are the closest! */
966  return GNUNET_YES;
967 }
968 
969 
987 static struct PeerInfo *
989  const struct GNUNET_CONTAINER_BloomFilter *bloom,
990  uint32_t hops)
991 {
992  unsigned int bc;
993  unsigned int count;
994  unsigned int selected;
995  struct PeerInfo *pos;
996  struct PeerInfo *chosen;
997 
998  if (hops >= GDS_NSE_get ())
999  {
1000  /* greedy selection (closest peer that is not in bloomfilter) */
1001  unsigned int best_bucket = 0;
1002  uint64_t best_in_bucket = UINT64_MAX;
1003 
1004  chosen = NULL;
1005  for (bc = 0; bc <= closest_bucket; bc++)
1006  {
1007  count = 0;
1008  for (pos = k_buckets[bc].head;
1009  (pos != NULL) &&
1010  (count < bucket_size);
1011  pos = pos->next)
1012  {
1013  unsigned int bucket;
1014  uint64_t dist;
1015 
1017  &pos->phash);
1018  dist = get_distance (key,
1019  &pos->phash,
1020  bucket);
1021  if (bucket < best_bucket)
1022  continue;
1023  if (dist > best_in_bucket)
1024  continue;
1025  best_bucket = bucket;
1026  best_in_bucket = dist;
1027  if ( (NULL == bloom) ||
1028  (GNUNET_NO ==
1030  &pos->phash)) )
1031  {
1032  chosen = pos;
1033  }
1034  else
1035  {
1037  "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1038  GNUNET_i2s (pos->id),
1039  GNUNET_h2s (key));
1041  gettext_noop (
1042  "# Peers excluded from routing due to Bloomfilter"),
1043  1,
1044  GNUNET_NO);
1045  chosen = NULL;
1046  }
1047  count++;
1048  }
1049  }
1050  if (NULL == chosen)
1052  gettext_noop ("# Peer selection failed"),
1053  1,
1054  GNUNET_NO);
1055  else
1057  "Selected peer `%s' in greedy routing for %s\n",
1058  GNUNET_i2s (chosen->id),
1059  GNUNET_h2s (key));
1060  return chosen;
1061  }
1062 
1063  /* select "random" peer */
1064  /* count number of peers that are available and not filtered */
1065  count = 0;
1066  for (bc = 0; bc <= closest_bucket; bc++)
1067  {
1068  pos = k_buckets[bc].head;
1069  while ((NULL != pos) && (count < bucket_size))
1070  {
1071  if ((NULL != bloom) &&
1072  (GNUNET_YES ==
1074  &pos->phash)))
1075  {
1077  gettext_noop
1078  (
1079  "# Peers excluded from routing due to Bloomfilter"),
1080  1, GNUNET_NO);
1082  "Excluded peer `%s' due to BF match in random routing for %s\n",
1083  GNUNET_i2s (pos->id),
1084  GNUNET_h2s (key));
1085  pos = pos->next;
1086  continue; /* Ignore bloomfiltered peers */
1087  }
1088  count++;
1089  pos = pos->next;
1090  }
1091  }
1092  if (0 == count) /* No peers to select from! */
1093  {
1095  gettext_noop ("# Peer selection failed"), 1,
1096  GNUNET_NO);
1097  return NULL;
1098  }
1099  /* Now actually choose a peer */
1101  count);
1102  count = 0;
1103  for (bc = 0; bc <= closest_bucket; bc++)
1104  {
1105  for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size));
1106  pos = pos->next)
1107  {
1108  if ((bloom != NULL) &&
1109  (GNUNET_YES ==
1111  &pos->phash)))
1112  {
1113  continue; /* Ignore bloomfiltered peers */
1114  }
1115  if (0 == selected--)
1116  {
1118  "Selected peer `%s' in random routing for %s\n",
1119  GNUNET_i2s (pos->id),
1120  GNUNET_h2s (key));
1121  return pos;
1122  }
1123  }
1124  }
1125  GNUNET_break (0);
1126  return NULL;
1127 }
1128 
1129 
1143 static unsigned int
1145  struct GNUNET_CONTAINER_BloomFilter *bloom,
1146  uint32_t hop_count,
1147  uint32_t target_replication,
1148  struct PeerInfo ***targets)
1149 {
1150  unsigned int ret;
1151  unsigned int off;
1152  struct PeerInfo **rtargets;
1153  struct PeerInfo *nxt;
1154 
1155  GNUNET_assert (NULL != bloom);
1156  ret = get_forward_count (hop_count,
1157  target_replication);
1158  if (0 == ret)
1159  {
1160  *targets = NULL;
1161  return 0;
1162  }
1163  rtargets = GNUNET_new_array (ret,
1164  struct PeerInfo *);
1165  for (off = 0; off < ret; off++)
1166  {
1167  nxt = select_peer (key,
1168  bloom,
1169  hop_count);
1170  if (NULL == nxt)
1171  break;
1172  rtargets[off] = nxt;
1175  &nxt->phash));
1177  &nxt->phash);
1178  }
1180  "Selected %u/%u peers at hop %u for %s (target was %u)\n",
1181  off,
1183  (unsigned int) hop_count,
1184  GNUNET_h2s (key),
1185  ret);
1186  if (0 == off)
1187  {
1188  GNUNET_free (rtargets);
1189  *targets = NULL;
1190  return 0;
1191  }
1192  *targets = rtargets;
1194  "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1195  GNUNET_h2s (key),
1196  off,
1197  ret);
1198  return off;
1199 }
1200 
1201 
1222 int
1225  uint32_t desired_replication_level,
1226  struct GNUNET_TIME_Absolute expiration_time,
1227  uint32_t hop_count,
1228  struct GNUNET_CONTAINER_BloomFilter *bf,
1229  const struct GNUNET_HashCode *key,
1230  unsigned int put_path_length,
1231  struct GNUNET_PeerIdentity *put_path,
1232  const void *data,
1233  size_t data_size)
1234 {
1235  unsigned int target_count;
1236  unsigned int i;
1237  struct PeerInfo **targets;
1238  struct PeerInfo *target;
1239  size_t msize;
1240  struct GNUNET_MQ_Envelope *env;
1241  struct PeerPutMessage *ppm;
1242  struct GNUNET_PeerIdentity *pp;
1243  unsigned int skip_count;
1244 
1245  GNUNET_assert (NULL != bf);
1247  "Adding myself (%s) to PUT bloomfilter for %s\n",
1249  GNUNET_h2s (key));
1251  &my_identity_hash);
1253  gettext_noop ("# PUT requests routed"),
1254  1,
1255  GNUNET_NO);
1256  target_count
1257  = get_target_peers (key,
1258  bf,
1259  hop_count,
1260  desired_replication_level,
1261  &targets);
1262  if (0 == target_count)
1263  {
1265  "Routing PUT for %s terminates after %u hops at %s\n",
1266  GNUNET_h2s (key),
1267  (unsigned int) hop_count,
1268  GNUNET_i2s (&my_identity));
1269  return GNUNET_NO;
1270  }
1271  msize = put_path_length * sizeof(struct GNUNET_PeerIdentity) + data_size;
1272  if (msize + sizeof(struct PeerPutMessage)
1274  {
1275  put_path_length = 0;
1276  msize = data_size;
1277  }
1278  if (msize + sizeof(struct PeerPutMessage)
1280  {
1281  GNUNET_break (0);
1282  GNUNET_free (targets);
1283  return GNUNET_NO;
1284  }
1286  gettext_noop (
1287  "# PUT messages queued for transmission"),
1288  target_count,
1289  GNUNET_NO);
1290  skip_count = 0;
1291  for (i = 0; i < target_count; i++)
1292  {
1293  target = targets[i];
1295  {
1296  /* skip */
1298  gettext_noop (
1299  "# P2P messages dropped due to full queue"),
1300  1,
1301  GNUNET_NO);
1302  skip_count++;
1303  continue;
1304  }
1306  "Routing PUT for %s after %u hops to %s\n",
1307  GNUNET_h2s (key),
1308  (unsigned int) hop_count,
1309  GNUNET_i2s (target->id));
1310  env = GNUNET_MQ_msg_extra (ppm,
1311  msize,
1313  ppm->options = htonl (options);
1314  ppm->type = htonl (type);
1315  ppm->hop_count = htonl (hop_count + 1);
1316  ppm->desired_replication_level = htonl (desired_replication_level);
1317  ppm->put_path_length = htonl (put_path_length);
1318  ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1321  &target->phash));
1324  ppm->bloomfilter,
1325  DHT_BLOOM_SIZE));
1326  ppm->key = *key;
1327  pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1328  GNUNET_memcpy (pp,
1329  put_path,
1330  sizeof(struct GNUNET_PeerIdentity) * put_path_length);
1331  GNUNET_memcpy (&pp[put_path_length],
1332  data,
1333  data_size);
1334  GNUNET_MQ_send (target->mq,
1335  env);
1336  }
1337  GNUNET_free (targets);
1338  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1339 }
1340 
1341 
1359 int
1362  uint32_t desired_replication_level,
1363  uint32_t hop_count,
1364  const struct GNUNET_HashCode *key,
1365  const void *xquery,
1366  size_t xquery_size,
1367  struct GNUNET_BLOCK_Group *bg,
1368  struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1369 {
1370  unsigned int target_count;
1371  struct PeerInfo **targets;
1372  struct PeerInfo *target;
1373  struct GNUNET_MQ_Envelope *env;
1374  size_t msize;
1375  struct PeerGetMessage *pgm;
1376  char *xq;
1377  size_t reply_bf_size;
1378  void *reply_bf;
1379  unsigned int skip_count;
1380  uint32_t bf_nonce;
1381 
1382  GNUNET_assert (NULL != peer_bf);
1384  gettext_noop ("# GET requests routed"),
1385  1,
1386  GNUNET_NO);
1387  target_count = get_target_peers (key,
1388  peer_bf,
1389  hop_count,
1391  &targets);
1393  "Adding myself (%s) to GET bloomfilter for %s\n",
1395  GNUNET_h2s (key));
1397  &my_identity_hash);
1398  if (0 == target_count)
1399  {
1401  "Routing GET for %s terminates after %u hops at %s\n",
1402  GNUNET_h2s (key),
1403  (unsigned int) hop_count,
1404  GNUNET_i2s (&my_identity));
1405  return GNUNET_NO;
1406  }
1407  if (GNUNET_OK !=
1409  &bf_nonce,
1410  &reply_bf,
1411  &reply_bf_size))
1412  {
1413  reply_bf = NULL;
1414  reply_bf_size = 0;
1416  UINT32_MAX);
1417  }
1418  msize = xquery_size + reply_bf_size;
1419  if (msize + sizeof(struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
1420  {
1421  GNUNET_break (0);
1422  GNUNET_free (reply_bf);
1423  GNUNET_free (targets);
1424  return GNUNET_NO;
1425  }
1427  gettext_noop (
1428  "# GET messages queued for transmission"),
1429  target_count,
1430  GNUNET_NO);
1431  /* forward request */
1432  skip_count = 0;
1433  for (unsigned int i = 0; i < target_count; i++)
1434  {
1435  target = targets[i];
1437  {
1438  /* skip */
1440  gettext_noop (
1441  "# P2P messages dropped due to full queue"),
1442  1, GNUNET_NO);
1443  skip_count++;
1444  continue;
1445  }
1447  "Routing GET for %s after %u hops to %s\n",
1448  GNUNET_h2s (key),
1449  (unsigned int) hop_count,
1450  GNUNET_i2s (target->id));
1451  env = GNUNET_MQ_msg_extra (pgm,
1452  msize,
1454  pgm->options = htonl (options);
1455  pgm->type = htonl (type);
1456  pgm->hop_count = htonl (hop_count + 1);
1458  pgm->xquery_size = htonl (xquery_size);
1459  pgm->bf_mutator = bf_nonce;
1462  &target->phash));
1465  pgm->bloomfilter,
1466  DHT_BLOOM_SIZE));
1467  pgm->key = *key;
1468  xq = (char *) &pgm[1];
1469  GNUNET_memcpy (xq,
1470  xquery,
1471  xquery_size);
1472  GNUNET_memcpy (&xq[xquery_size],
1473  reply_bf,
1474  reply_bf_size);
1475  GNUNET_MQ_send (target->mq,
1476  env);
1477  }
1478  GNUNET_free (targets);
1479  GNUNET_free (reply_bf);
1480  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1481 }
1482 
1483 
1500 void
1502  enum GNUNET_BLOCK_Type type,
1503  struct GNUNET_TIME_Absolute expiration_time,
1504  const struct GNUNET_HashCode *key,
1505  unsigned int put_path_length,
1506  const struct GNUNET_PeerIdentity *put_path,
1507  unsigned int get_path_length,
1508  const struct GNUNET_PeerIdentity *get_path,
1509  const void *data,
1510  size_t data_size)
1511 {
1512  struct PeerInfo *pi;
1513  struct GNUNET_MQ_Envelope *env;
1514  size_t msize;
1515  struct PeerResultMessage *prm;
1516  struct GNUNET_PeerIdentity *paths;
1517 
1518  msize = data_size + (get_path_length + put_path_length)
1519  * sizeof(struct GNUNET_PeerIdentity);
1520  if ((msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
1521  (get_path_length >
1522  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1523  (put_path_length >
1524  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1526  {
1527  GNUNET_break (0);
1528  return;
1529  }
1531  target);
1532  if (NULL == pi)
1533  {
1534  /* peer disconnected in the meantime, drop reply */
1536  "No matching peer for reply for key %s\n",
1537  GNUNET_h2s (key));
1538  return;
1539  }
1541  {
1542  /* skip */
1544  gettext_noop (
1545  "# P2P messages dropped due to full queue"),
1546  1,
1547  GNUNET_NO);
1549  "Peer queue full, ignoring reply for key %s\n",
1550  GNUNET_h2s (key));
1551  return;
1552  }
1553 
1555  "Forwarding reply for key %s to peer %s\n",
1556  GNUNET_h2s (key),
1557  GNUNET_i2s (target));
1559  gettext_noop
1560  ("# RESULT messages queued for transmission"), 1,
1561  GNUNET_NO);
1562  env = GNUNET_MQ_msg_extra (prm,
1563  msize,
1565  prm->type = htonl (type);
1566  prm->put_path_length = htonl (put_path_length);
1567  prm->get_path_length = htonl (get_path_length);
1568  prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1569  prm->key = *key;
1570  paths = (struct GNUNET_PeerIdentity *) &prm[1];
1571  GNUNET_memcpy (paths,
1572  put_path,
1573  put_path_length * sizeof(struct GNUNET_PeerIdentity));
1574  GNUNET_memcpy (&paths[put_path_length],
1575  get_path,
1576  get_path_length * sizeof(struct GNUNET_PeerIdentity));
1577  GNUNET_memcpy (&paths[put_path_length + get_path_length],
1578  data,
1579  data_size);
1580  GNUNET_MQ_send (pi->mq,
1581  env);
1582 }
1583 
1584 
1591 static void
1592 core_init (void *cls,
1593  const struct GNUNET_PeerIdentity *identity)
1594 {
1595  (void) cls;
1597  "CORE called, I am %s\n",
1598  GNUNET_i2s (identity));
1599  my_identity = *identity;
1601  sizeof(struct GNUNET_PeerIdentity),
1602  &my_identity_hash);
1604 }
1605 
1606 
1614 static int
1616  const struct PeerPutMessage *put)
1617 {
1618  uint32_t putlen;
1619  uint16_t msize;
1620 
1621  (void) cls;
1622  msize = ntohs (put->header.size);
1623  putlen = ntohl (put->put_path_length);
1624  if ((msize <
1625  sizeof(struct PeerPutMessage)
1626  + putlen * sizeof(struct GNUNET_PeerIdentity)) ||
1627  (putlen >
1628  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
1629  {
1630  GNUNET_break_op (0);
1631  return GNUNET_SYSERR;
1632  }
1633  return GNUNET_OK;
1634 }
1635 
1636 
1643 static void
1645  const struct PeerPutMessage *put)
1646 {
1647  struct PeerInfo *peer = cls;
1648  const struct GNUNET_PeerIdentity *put_path;
1649  const void *payload;
1650  uint32_t putlen;
1651  uint16_t msize;
1652  size_t payload_size;
1654  struct GNUNET_CONTAINER_BloomFilter *bf;
1655  struct GNUNET_HashCode test_key;
1656  int forwarded;
1657  struct GNUNET_TIME_Absolute exp_time;
1658 
1659  exp_time = GNUNET_TIME_absolute_ntoh (put->expiration_time);
1660  if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
1661  {
1663  gettext_noop ("# Expired PUTs discarded"),
1664  1,
1665  GNUNET_NO);
1666  return;
1667  }
1668  msize = ntohs (put->header.size);
1669  putlen = ntohl (put->put_path_length);
1671  gettext_noop ("# P2P PUT requests received"),
1672  1,
1673  GNUNET_NO);
1675  gettext_noop ("# P2P PUT bytes received"),
1676  msize,
1677  GNUNET_NO);
1678  put_path = (const struct GNUNET_PeerIdentity *) &put[1];
1679  payload = &put_path[putlen];
1680  options = ntohl (put->options);
1681  payload_size = msize - (sizeof(struct PeerPutMessage)
1682  + putlen * sizeof(struct GNUNET_PeerIdentity));
1683 
1685  "PUT for `%s' from %s\n",
1686  GNUNET_h2s (&put->key),
1687  GNUNET_i2s (peer->id));
1689  {
1690  char *tmp;
1691  char *pp;
1692 
1693  pp = GNUNET_STRINGS_pp2s (put_path,
1694  putlen);
1697  "R5N PUT %s: %s->%s (%u, %u=>%u, PP: %s)\n",
1698  GNUNET_h2s (&put->key),
1699  GNUNET_i2s (peer->id),
1700  tmp,
1701  ntohl (put->hop_count),
1703  &put->key),
1705  &put->key),
1706  pp);
1707  GNUNET_free (pp);
1708  GNUNET_free (tmp);
1709  }
1710  switch (GNUNET_BLOCK_get_key
1712  ntohl (put->type),
1713  payload,
1714  payload_size,
1715  &test_key))
1716  {
1717  case GNUNET_YES:
1718  if (0 != memcmp (&test_key,
1719  &put->key,
1720  sizeof(struct GNUNET_HashCode)))
1721  {
1722  char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
1723 
1724  GNUNET_break_op (0);
1726  "PUT with key `%s' for block with key %s\n",
1727  put_s,
1728  GNUNET_h2s_full (&test_key));
1729  GNUNET_free (put_s);
1730  return;
1731  }
1732  break;
1733 
1734  case GNUNET_NO:
1735  GNUNET_break_op (0);
1736  return;
1737 
1738  case GNUNET_SYSERR:
1739  /* cannot verify, good luck */
1740  break;
1741  }
1742  if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
1743  {
1745  ntohl (put->type),
1746  NULL, /* query group */
1748  NULL, /* query */
1749  NULL, 0, /* xquery */
1750  payload,
1751  payload_size))
1752  {
1755  break;
1756 
1763  default:
1764  GNUNET_break_op (0);
1765  return;
1766  }
1767  }
1768 
1774  &peer->phash));
1775  {
1776  struct GNUNET_PeerIdentity pp[putlen + 1];
1777 
1778  /* extend 'put path' by sender */
1779  if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1780  {
1781 #if SANITY_CHECKS
1782  for (unsigned int i = 0; i <= putlen; i++)
1783  {
1784  for (unsigned int j = 0; j < i; j++)
1785  {
1786  GNUNET_break (0 != memcmp (&pp[i],
1787  &pp[j],
1788  sizeof(struct GNUNET_PeerIdentity)));
1789  }
1790  GNUNET_break (0 != memcmp (&pp[i],
1791  peer->id,
1792  sizeof(struct GNUNET_PeerIdentity)));
1793  }
1794 #endif
1795  GNUNET_memcpy (pp,
1796  put_path,
1797  putlen * sizeof(struct GNUNET_PeerIdentity));
1798  pp[putlen] = *peer->id;
1799  putlen++;
1800  }
1801  else
1802  putlen = 0;
1803 
1804  /* give to local clients */
1805  GDS_CLIENTS_handle_reply (exp_time,
1806  &put->key,
1807  0,
1808  NULL,
1809  putlen,
1810  pp,
1811  ntohl (put->type),
1812  payload_size,
1813  payload);
1814  /* store locally */
1816  (GDS_am_closest_peer (&put->key, bf)))
1817  GDS_DATACACHE_handle_put (exp_time,
1818  &put->key,
1819  putlen,
1820  pp,
1821  ntohl (put->type),
1822  payload_size,
1823  payload);
1824  /* route to other peers */
1825  forwarded = GDS_NEIGHBOURS_handle_put (ntohl (put->type),
1826  options,
1827  ntohl (
1829  exp_time,
1830  ntohl (put->hop_count),
1831  bf,
1832  &put->key,
1833  putlen,
1834  pp,
1835  payload,
1836  payload_size);
1837  /* notify monitoring clients */
1839  | ((GNUNET_OK == forwarded)
1841  : 0),
1842  ntohl (put->type),
1843  ntohl (put->hop_count),
1844  ntohl (put->desired_replication_level),
1845  putlen, pp,
1846  exp_time,
1847  &put->key,
1848  payload,
1849  payload_size);
1850  }
1852 }
1853 
1854 
1863 static void
1865  const struct GNUNET_HashCode *key,
1866  struct GNUNET_BLOCK_Group *bg)
1867 {
1868  int bucket_idx;
1869  struct PeerBucket *bucket;
1870  struct PeerInfo *peer;
1871  unsigned int choice;
1872  const struct GNUNET_HELLO_Message *hello;
1873  size_t hello_size;
1874 
1875  /* first, check about our own HELLO */
1876  if (NULL != GDS_my_hello)
1877  {
1878  hello_size = GNUNET_HELLO_size ((const struct
1880  GNUNET_break (hello_size >= sizeof(struct GNUNET_MessageHeader));
1884  bg,
1887  NULL, 0,
1888  GDS_my_hello,
1889  hello_size))
1890  {
1895  key,
1896  0,
1897  NULL,
1898  0,
1899  NULL,
1900  GDS_my_hello,
1901  hello_size);
1902  }
1903  else
1904  {
1906  gettext_noop (
1907  "# FIND PEER requests ignored due to Bloomfilter"),
1908  1,
1909  GNUNET_NO);
1910  }
1911  }
1912  else
1913  {
1915  gettext_noop (
1916  "# FIND PEER requests ignored due to lack of HELLO"),
1917  1,
1918  GNUNET_NO);
1919  }
1920 
1921  /* then, also consider sending a random HELLO from the closest bucket */
1922  if (0 == memcmp (&my_identity_hash,
1923  key,
1924  sizeof(struct GNUNET_HashCode)))
1925  bucket_idx = closest_bucket;
1926  else
1927  bucket_idx = GNUNET_MIN ((int) closest_bucket,
1928  find_bucket (key));
1929  if (bucket_idx < 0)
1930  return;
1931  bucket = &k_buckets[bucket_idx];
1932  if (bucket->peers_size == 0)
1933  return;
1935  bucket->peers_size);
1936  peer = bucket->head;
1937  while (choice > 0)
1938  {
1939  GNUNET_assert (NULL != peer);
1940  peer = peer->next;
1941  choice--;
1942  }
1943  choice = bucket->peers_size;
1944  do
1945  {
1946  peer = peer->next;
1947  if (0 == choice--)
1948  return; /* no non-masked peer available */
1949  if (NULL == peer)
1950  peer = bucket->head;
1951  hello = GDS_HELLO_get (peer->id);
1952  }
1953  while ((NULL == hello) ||
1957  bg,
1959  &peer->phash,
1960  NULL, 0,
1961  hello,
1962  (hello_size = GNUNET_HELLO_size (hello)))));
1967  key,
1968  0,
1969  NULL,
1970  0,
1971  NULL,
1972  hello,
1973  hello_size);
1974 }
1975 
1976 
1991 static void
1993  enum GNUNET_BLOCK_Type type,
1994  struct GNUNET_TIME_Absolute expiration_time,
1995  const struct GNUNET_HashCode *key,
1996  unsigned int put_path_length,
1997  const struct GNUNET_PeerIdentity *put_path,
1998  unsigned int get_path_length,
1999  const struct GNUNET_PeerIdentity *get_path,
2000  const void *data,
2001  size_t data_size)
2002 {
2003  struct PeerInfo *peer = cls;
2004  char *pp;
2005 
2006  pp = GNUNET_STRINGS_pp2s (put_path,
2007  put_path_length);
2009  "Found local result for %s (PP: %s)\n",
2010  GNUNET_h2s (key),
2011  pp);
2012  GNUNET_free (pp);
2014  type,
2015  expiration_time,
2016  key,
2017  put_path_length, put_path,
2018  get_path_length, get_path,
2019  data, data_size);
2020 }
2021 
2022 
2030 static int
2032  const struct PeerGetMessage *get)
2033 {
2034  uint32_t xquery_size;
2035  uint16_t msize;
2036 
2037  (void) cls;
2038  msize = ntohs (get->header.size);
2039  xquery_size = ntohl (get->xquery_size);
2040  if (msize < sizeof(struct PeerGetMessage) + xquery_size)
2041  {
2042  GNUNET_break_op (0);
2043  return GNUNET_SYSERR;
2044  }
2045  return GNUNET_OK;
2046 }
2047 
2048 
2055 static void
2057  const struct PeerGetMessage *get)
2058 {
2059  struct PeerInfo *peer = cls;
2060  uint32_t xquery_size;
2061  size_t reply_bf_size;
2062  uint16_t msize;
2063  enum GNUNET_BLOCK_Type type;
2066  struct GNUNET_BLOCK_Group *bg;
2067  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2068  const char *xquery;
2069  int forwarded;
2070 
2071  /* parse and validate message */
2072  msize = ntohs (get->header.size);
2073  xquery_size = ntohl (get->xquery_size);
2074  reply_bf_size = msize - (sizeof(struct PeerGetMessage) + xquery_size);
2075  type = ntohl (get->type);
2076  options = ntohl (get->options);
2077  xquery = (const char *) &get[1];
2079  gettext_noop ("# P2P GET requests received"),
2080  1,
2081  GNUNET_NO);
2083  gettext_noop ("# P2P GET bytes received"),
2084  msize,
2085  GNUNET_NO);
2087  {
2088  char *tmp;
2089 
2092  "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
2093  GNUNET_h2s (&get->key),
2094  GNUNET_i2s (peer->id),
2095  tmp,
2096  ntohl (get->hop_count),
2098  &get->key),
2100  &get->key),
2101  ntohl (get->xquery_size),
2102  xquery);
2103  GNUNET_free (tmp);
2104  }
2105  eval
2107  type,
2108  NULL,
2110  &get->key,
2111  xquery,
2112  xquery_size,
2113  NULL,
2114  0);
2116  {
2117  /* request invalid or block type not supported */
2119  return;
2120  }
2126  &peer->phash));
2128  type,
2129  get->bf_mutator,
2130  &xquery[xquery_size],
2131  reply_bf_size,
2132  "filter-size",
2133  reply_bf_size,
2134  NULL);
2136  "GET for %s at %s after %u hops\n",
2137  GNUNET_h2s (&get->key),
2139  (unsigned int) ntohl (get->hop_count));
2140  /* local lookup (this may update the reply_bf) */
2142  (GDS_am_closest_peer (&get->key,
2143  peer_bf)))
2144  {
2145  if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
2146  {
2148  gettext_noop (
2149  "# P2P FIND PEER requests processed"),
2150  1,
2151  GNUNET_NO);
2152  handle_find_peer (peer->id,
2153  &get->key,
2154  bg);
2155  }
2156  else
2157  {
2158  eval = GDS_DATACACHE_handle_get (&get->key,
2159  type,
2160  xquery,
2161  xquery_size,
2162  bg,
2164  peer);
2165  }
2166  }
2167  else
2168  {
2170  gettext_noop ("# P2P GET requests ONLY routed"),
2171  1,
2172  GNUNET_NO);
2173  }
2174 
2175  /* remember request for routing replies */
2176  GDS_ROUTING_add (peer->id,
2177  type,
2178  bg, /* bg now owned by routing, but valid at least until end of this function! */
2179  options,
2180  &get->key,
2181  xquery,
2182  xquery_size);
2183 
2184  /* P2P forwarding */
2185  forwarded = GNUNET_NO;
2186  if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
2187  forwarded = GDS_NEIGHBOURS_handle_get (type,
2188  options,
2189  ntohl (
2191  ntohl (get->hop_count),
2192  &get->key,
2193  xquery,
2194  xquery_size,
2195  bg,
2196  peer_bf);
2198  | ((GNUNET_OK == forwarded)
2199  ? GNUNET_DHT_RO_LAST_HOP : 0),
2200  type,
2201  ntohl (get->hop_count),
2202  ntohl (get->desired_replication_level),
2203  0,
2204  NULL,
2205  &get->key);
2206 
2207  /* clean up; note that 'bg' is owned by routing now! */
2209 }
2210 
2211 
2219 static int
2221  const struct PeerResultMessage *prm)
2222 {
2223  uint32_t get_path_length;
2224  uint32_t put_path_length;
2225  uint16_t msize;
2226 
2227  (void) cls;
2228  msize = ntohs (prm->header.size);
2229  put_path_length = ntohl (prm->put_path_length);
2230  get_path_length = ntohl (prm->get_path_length);
2231  if ((msize <
2232  sizeof(struct PeerResultMessage) + (get_path_length
2233  + put_path_length)
2234  * sizeof(struct GNUNET_PeerIdentity)) ||
2235  (get_path_length >
2236  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
2237  (put_path_length >
2238  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
2239  {
2240  GNUNET_break_op (0);
2241  return GNUNET_SYSERR;
2242  }
2243  return GNUNET_OK;
2244 }
2245 
2246 
2260 static void
2262  const struct GNUNET_HashCode *key,
2263  unsigned int get_path_length,
2264  const struct GNUNET_PeerIdentity *get_path,
2265  unsigned int put_path_length,
2266  const struct GNUNET_PeerIdentity *put_path,
2267  enum GNUNET_BLOCK_Type type,
2268  size_t data_size,
2269  const void *data)
2270 {
2271  /* forward to local clients */
2272  GDS_CLIENTS_handle_reply (expiration_time,
2273  key,
2274  get_path_length,
2275  get_path,
2276  put_path_length,
2277  put_path,
2278  type,
2279  data_size,
2280  data);
2282  get_path,
2283  get_path_length,
2284  put_path,
2285  put_path_length,
2286  expiration_time,
2287  key,
2288  data,
2289  data_size);
2290  if (GNUNET_YES == cache_results)
2291  {
2292  struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length];
2293 
2294  GNUNET_memcpy (xput_path,
2295  put_path,
2296  put_path_length * sizeof(struct GNUNET_PeerIdentity));
2297  GNUNET_memcpy (&xput_path[put_path_length],
2298  get_path,
2299  get_path_length * sizeof(struct GNUNET_PeerIdentity));
2300 
2301  GDS_DATACACHE_handle_put (expiration_time,
2302  key,
2303  get_path_length + put_path_length,
2304  xput_path,
2305  type,
2306  data_size,
2307  data);
2308  }
2309  /* forward to other peers */
2311  expiration_time,
2312  key,
2313  put_path_length,
2314  put_path,
2315  get_path_length,
2316  get_path,
2317  data,
2318  data_size);
2319 }
2320 
2321 
2328 static void
2330  const struct PeerResultMessage *prm)
2331 {
2332  struct PeerInfo *peer = cls;
2333  const struct GNUNET_PeerIdentity *put_path;
2334  const struct GNUNET_PeerIdentity *get_path;
2335  const void *data;
2336  uint32_t get_path_length;
2337  uint32_t put_path_length;
2338  uint16_t msize;
2339  size_t data_size;
2340  enum GNUNET_BLOCK_Type type;
2341  struct GNUNET_TIME_Absolute exp_time;
2342 
2343  /* parse and validate message */
2344  exp_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time);
2345  if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
2346  {
2348  gettext_noop ("# Expired results discarded"),
2349  1,
2350  GNUNET_NO);
2351  return;
2352  }
2353  msize = ntohs (prm->header.size);
2354  put_path_length = ntohl (prm->put_path_length);
2355  get_path_length = ntohl (prm->get_path_length);
2356  put_path = (const struct GNUNET_PeerIdentity *) &prm[1];
2357  get_path = &put_path[put_path_length];
2358  type = ntohl (prm->type);
2359  data = (const void *) &get_path[get_path_length];
2360  data_size = msize - (sizeof(struct PeerResultMessage)
2361  + (get_path_length
2362  + put_path_length) * sizeof(struct
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 */
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;
2512  NULL,
2513  &core_init,
2516  core_handlers);
2517  if (NULL == core_api)
2518  return GNUNET_SYSERR;
2520  GNUNET_YES);
2522  GNUNET_NO);
2523  return GNUNET_OK;
2524 }
2525 
2526 
2530 void
2532 {
2533  if (NULL == core_api)
2534  return;
2536  core_api = NULL;
2537  GNUNET_assert (0 ==
2540  all_connected_peers = NULL;
2543  NULL);
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 */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
char * getenv()
#define gettext_noop(String)
Definition: gettext.h:69
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static struct PendingResolutions * head
Head of list of pending resolution requests.
Definition: gnunet-ats.c:230
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
struct GNUNET_HashCode key
The key used in the DHT.
uint32_t data
The data value.
static char * value
Value of the record to add/remove.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
static unsigned long long payload
How much data are we currently storing in the database?
struct GNUNET_MessageHeader * GDS_my_hello
Our HELLO.
GNUnet DHT globals.
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.
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
struct GNUNET_BLOCK_Context * GDS_block_context
Our handle to the BLOCK library.
struct GNUNET_SERVICE_Handle * GDS_service
Handle for the service.
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.
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.
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
Configuration we use.
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've received from another peer.
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've received from another peer.
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've received from another peer.
GNUnet DHT service's datacache integration.
const struct GNUNET_HELLO_Message * GDS_HELLO_get(const struct GNUNET_PeerIdentity *peer)
Obtain a peer's HELLO if available.
GNUnet DHT integration with peerinfo.
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...
static void handle_dht_p2p_result(void *cls, const struct PeerResultMessage *prm)
Core handler for p2p result messages.
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.
static struct GNUNET_CONTAINER_MultiPeerMap * all_desired_peers
Hash map of all peers we would like to be connected to.
static int check_dht_p2p_put(void *cls, const struct PeerPutMessage *put)
Check validity of a p2p put request.
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.
static void core_init(void *cls, const struct GNUNET_PeerIdentity *identity)
To be called on core init/fail.
#define MAXIMUM_PENDING_PER_PEER
Maximum allowed number of pending messages per peer.
static int disable_try_connect
Option for testing that disables the 'connect' function of the DHT.
static 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.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static int check_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Check validity of p2p get request.
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...
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.
static unsigned int newly_found_peers
How many peers have we added since we sent out our last find peer request?
#define DEFAULT_BUCKET_SIZE
What is the maximum number of peers in a given bucket.
void GDS_NEIGHBOURS_done()
Shutdown neighbours subsystem.
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't get duplica...
static void handle_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Core handler for p2p get requests.
static struct GNUNET_ATS_ConnectivityHandle * ats_ch
Handle to ATS connectivity.
#define FIND_PEER_REPLICATION_LEVEL
Desired replication level for FIND PEER requests.
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.
static void update_connect_preferences()
Update our preferences for connectivity as given to ATS.
static struct PeerInfo * select_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops)
Select a peer from the routing table that would be a good routing destination for sending a message f...
static int find_bucket(const struct GNUNET_HashCode *hc)
Find the optimal bucket for this key.
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.
static struct GNUNET_CONTAINER_MultiPeerMap * all_connected_peers
Hash map of all CORE-connected peers, for easy removal from k_buckets on disconnect.
struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id()
Get the ID of the local node.
#define DHT_MINIMUM_FIND_PEER_INTERVAL
How long at least to wait before sending another find peer request.
struct GNUNET_TIME_Relative hello_expiration
Hello address expiration.
static int cache_results
Do we cache all results that we are routing in the local datacache?
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.
static struct GNUNET_SCHEDULER_Task * find_peer_task
Task that sends FIND PEER requests.
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.
#define MAX_BUCKETS
How many buckets will we allow total.
static struct GNUNET_CORE_Handle * core_api
Handle to CORE.
struct GNUNET_HashCode my_identity_hash
Hash of the identity of this peer.
static unsigned int bucket_size
Maximum size for each bucket.
#define DHT_MAXIMUM_FIND_PEER_INTERVAL
How long at most to wait before sending another find peer request.
#define MAXIMUM_REPLICATION_LEVEL
Maximum allowed replication level for all requests.
static unsigned int closest_bucket
The lowest currently used bucket, initially 0 (for 0-bits matching bucket).
static void offer_hello_done(void *cls)
Function called when GNUNET_TRANSPORT_offer_hello() is done.
static int log_route_details_stderr
Should routing details be logged to stderr (for debugging)?
static int check_dht_p2p_result(void *cls, const struct PeerResultMessage *prm)
Check validity of p2p result message.
static struct PeerBucket k_buckets[sizeof(struct GNUNET_HashCode) *8]
The buckets.
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.
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.
#define LOG_TRAFFIC(kind,...)
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...
static void handle_core_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls)
Method called whenever a peer disconnects.
static void * handle_core_connect(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a peer connects.
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).
static void handle_dht_p2p_put(void *cls, const struct PeerPutMessage *put)
Core handler for p2p put requests.
int GDS_NEIGHBOURS_init()
Initialize neighbours subsystem.
GNUnet DHT routing code.
double GDS_NSE_get()
Return the log of the current network size estimate.
GNUnet DHT integration with NSE.
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).
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.
GNUnet DHT tracking of requests for routing replies.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
Automatic transport selection and outbound bandwidth determination.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
#define GNUNET_MIN(a, b)
#define GNUNET_PACKED
gcc-ism to get packed structs.
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 GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_ATS_ConnectivityHandle * GNUNET_ATS_connectivity_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the ATS connectivity suggestion client handle.
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.
void GNUNET_ATS_connectivity_done(struct GNUNET_ATS_ConnectivityHandle *ch)
Client is done with ATS connectivity management, release resources.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
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
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition: block.c:206
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
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
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
GNUNET_BLOCK_EvaluationResult
Possible ways for how a block may relate to a query.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
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
@ GNUNET_BLOCK_EVALUATION_RESULT_INVALID
Block does not match query (invalid result)
@ GNUNET_BLOCK_EVALUATION_REQUEST_INVALID
Query format does not match block type (invalid query).
@ GNUNET_BLOCK_EVALUATION_OK_LAST
Last possible valid result.
@ GNUNET_BLOCK_EVALUATION_OK_MORE
Valid result, and there may be more.
@ GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT
Block does not match xquery (valid result, not relevant for the request)
@ GNUNET_BLOCK_EVALUATION_OK_DUPLICATE
Valid result, but suppressed because it is a duplicate.
@ GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED
Specified block type not supported by this plugin.
@ GNUNET_BLOCK_EVALUATION_REQUEST_VALID
Query is valid, no reply given.
@ GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO
The block is obtained from the local database, skip cryptographic checks.
@ GNUNET_BLOCK_EO_NONE
Default behavior.
@ GNUNET_BLOCK_TYPE_REGEX
Block to store a cadet regex state.
@ GNUNET_BLOCK_TYPE_DHT_HELLO
Type of a block that contains a HELLO for a peer (for DHT and CADET find-peer operations).
int GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this Bloom filter into the given data array.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
int GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION
After how long do we expire an address in a HELLO that we just validated? This value is also used for...
#define GNUNET_CONSTANTS_BLOOMFILTER_K
K-value that must be used for the bloom filters in 'GET' queries.
#define GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
What is the maximum size for encrypted messages? Note that this number imposes a clear limit on the m...
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
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
GNUNET_DHT_RouteOption
Options for routing.
@ GNUNET_DHT_RO_RECORD_ROUTE
We should keep track of the route that the message took in the P2P network.
@ GNUNET_DHT_RO_LAST_HOP
Flag given to monitors if this was the last hop for a GET/PUT.
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should look at 'enc' (otherwise only the k-peers closest to the key should lo...
@ GNUNET_DHT_RO_FIND_PEER
This is a 'FIND-PEER' request, so approximate results are fine.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
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
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
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
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.
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.
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).
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
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
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:652
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:337
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
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
Data is returned to peer from DHT.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_GET
Peer tries to find data in DHT.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
Peer is storing data in DHT.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2195
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
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_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
#define GNUNET_TIME_UNIT_MINUTES
One minute.
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 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
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:464
void GNUNET_TRANSPORT_offer_hello_cancel(struct GNUNET_TRANSPORT_OfferHelloHandle *ohh)
Cancel the request to transport to offer the HELLO message.
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.
Information about a peer that we would like to connect to.
struct GNUNET_TRANSPORT_OfferHelloHandle * oh
Handle to active HELLO offer operation, or NULL.
uint32_t strength
How much would we like to connect to this peer?
struct GNUNET_ATS_ConnectivitySuggestHandle * sh
Handle to active connectivity suggestion operation, or NULL.
Handle to the ATS subsystem for connectivity management.
Handle for ATS address suggestion requests.
Block group data.
Internal representation of the hash map.
Context for the core service connection.
Definition: core_api.c:78
A HELLO message is used to exchange information about transports with other peers.
A 512-bit hashcode.
uint32_t bits[512/8/sizeof(uint32_t)]
Handle to a message queue.
Definition: mq.c:86
Message handler for a specific message type.
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_MQ_Handle * mq
Connection to the service.
Definition: peerinfo_api.c:94
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:135
struct GNUNET_TESTBED_Peer * next
peer list DLL
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Entry in linked list for all offer-HELLO requests.
Peers are grouped into buckets.
struct PeerInfo * head
Head of DLL.
struct PeerInfo * tail
Tail of DLL.
unsigned int peers_size
Number of peers in the bucket.
uint32_t bf_mutator
Bloomfilter mutator.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
uint32_t hop_count
Hop count.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_GET.
uint32_t xquery_size
Size of the extended query.
struct GNUNET_HashCode key
The key we are looking for.
uint32_t type
Desired content type.
uint32_t desired_replication_level
Desired replication level for this request.
uint32_t options
Processing options.
Entry for a peer in a bucket.
struct PeerInfo * next
Next peer entry (DLL)
struct GNUNET_MQ_Handle * mq
Handle for sending messages to this peer.
struct PeerInfo * prev
Prev peer entry (DLL)
struct GNUNET_HashCode phash
Hash of id.
int peer_bucket
Which bucket is this peer in?
const struct GNUNET_PeerIdentity * id
What is the identity of the peer?
uint32_t options
Processing options.
uint32_t type
Content type.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT.
struct GNUNET_HashCode key
The key we are storing under.
uint32_t desired_replication_level
Replication level for this message.
uint32_t put_path_length
Length of the PUT path that follows (if tracked).
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
uint32_t hop_count
Hop count.
uint32_t get_path_length
Length of the GET path that follows (if tracked).
uint32_t put_path_length
Length of the PUT path that follows (if tracked).
struct GNUNET_HashCode key
The key of the corresponding GET request.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT.
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.