GNUnet  0.10.x
gnunet-service-dht_neighbours.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_nse_service.h"
34 #include "gnunet_ats_service.h"
35 #include "gnunet_core_service.h"
36 #include "gnunet_datacache_lib.h"
38 #include "gnunet_hello_lib.h"
39 #include "gnunet_dht_service.h"
41 #include "gnunet-service-dht.h"
45 #include "gnunet-service-dht_nse.h"
47 #include "dht.h"
48 
49 #define LOG_TRAFFIC(kind, ...) GNUNET_log_from(kind, "dht-traffic", __VA_ARGS__)
50 
54 #define SANITY_CHECKS 1
55 
59 #define MAX_BUCKETS sizeof(struct GNUNET_HashCode) * 8
60 
64 #define DEFAULT_BUCKET_SIZE 8
65 
69 #define FIND_PEER_REPLICATION_LEVEL 4
70 
74 #define MAXIMUM_REPLICATION_LEVEL 16
75 
79 #define MAXIMUM_PENDING_PER_PEER 64
80 
84 #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
85 
89 #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
90 
94 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
95 
100 
101 
103 
112 
117 
121  uint32_t type GNUNET_PACKED;
122 
127 
132 
137 
142 
147 
152 
153  /* put path (if tracked) */
154 
155  /* Payload */
156 };
157 
158 
167 
171  uint32_t type GNUNET_PACKED;
172 
177 
181  uint32_t get_path_length GNUNET_PACKED;
182 
187 
191  struct GNUNET_HashCode key;
192 
193  /* put path (if tracked) */
194 
195  /* get path (if tracked) */
196 
197  /* Payload */
198 };
199 
200 
209 
214 
218  uint32_t type GNUNET_PACKED;
219 
224 
229 
233  uint32_t xquery_size;
234 
238  uint32_t bf_mutator;
239 
244 
248  struct GNUNET_HashCode key;
249 
250  /* xquery */
251 
252  /* result bloomfilter */
253 };
255 
256 
260 struct PeerInfo {
264  struct PeerInfo *next;
265 
269  struct PeerInfo *prev;
270 
275 
279  const struct GNUNET_PeerIdentity *id;
280 
284  struct GNUNET_HashCode phash;
285 
290 };
291 
292 
296 struct PeerBucket {
300  struct PeerInfo *head;
301 
305  struct PeerInfo *tail;
306 
310  unsigned int peers_size;
311 };
312 
313 
317 struct ConnectInfo {
322 
327 
331  uint32_t strength;
332 };
333 
334 
338 static int cache_results;
339 
344 
348 static unsigned int closest_bucket;
349 
354 static unsigned int newly_found_peers;
355 
360 
365 
371 
377 
381 static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
382 
387 
392 
397 
402 
407 
408 
416 static int
417 find_bucket(const struct GNUNET_HashCode *hc)
418 {
419  unsigned int bits;
420 
422  if (bits == MAX_BUCKETS)
423  {
424  /* How can all bits match? Got my own ID? */
425  GNUNET_break(0);
426  return GNUNET_SYSERR;
427  }
428  return MAX_BUCKETS - bits - 1;
429 }
430 
431 
438 static void
440 {
441  struct ConnectInfo *ci = cls;
442 
443  ci->oh = NULL;
444 }
445 
446 
455 static int
457  const struct GNUNET_PeerIdentity *peer,
458  void *value)
459 {
460  struct ConnectInfo *ci = value;
461 
462  (void)cls;
464  GNUNET_CONTAINER_multipeermap_remove(all_desired_peers,
465  peer,
466  ci));
467  if (NULL != ci->sh)
468  {
470  ci->sh = NULL;
471  }
472  if (NULL != ci->oh)
473  {
475  ci->oh = NULL;
476  }
477  GNUNET_free(ci);
478  return GNUNET_YES;
479 }
480 
481 
490 static void
492  const struct GNUNET_MessageHeader *h)
493 {
494  int bucket;
495  struct GNUNET_HashCode pid_hash;
496  struct ConnectInfo *ci;
497  uint32_t strength;
498 
499  GNUNET_CRYPTO_hash(pid,
500  sizeof(struct GNUNET_PeerIdentity),
501  &pid_hash);
502  bucket = find_bucket(&pid_hash);
503  if (bucket < 0)
504  return; /* self? */
505  ci = GNUNET_CONTAINER_multipeermap_get(all_desired_peers,
506  pid);
507 
508  if (k_buckets[bucket].peers_size < bucket_size)
509  strength = (bucket_size - k_buckets[bucket].peers_size) * bucket;
510  else
511  strength = bucket; /* minimum value of connectivity */
512  if (GNUNET_YES ==
513  GNUNET_CONTAINER_multipeermap_contains(all_connected_peers,
514  pid))
515  strength *= 2; /* double for connected peers */
516  else if (k_buckets[bucket].peers_size > bucket_size)
517  strength = 0; /* bucket full, we really do not care about more */
518 
519  if ((0 == strength) &&
520  (NULL != ci))
521  {
522  /* release request */
524  free_connect_info(NULL,
525  pid,
526  ci));
527  return;
528  }
529  if (NULL == ci)
530  {
531  ci = GNUNET_new(struct ConnectInfo);
533  GNUNET_CONTAINER_multipeermap_put(all_desired_peers,
534  pid,
535  ci,
537  }
538  if ((NULL != ci->oh) &&
539  (NULL != h))
541  if (NULL != h)
543  h,
545  ci);
546  if ((NULL != ci->sh) &&
547  (ci->strength != strength))
549  if (ci->strength != strength)
550  ci->sh = GNUNET_ATS_connectivity_suggest(ats_ch,
551  pid,
552  strength);
553  ci->strength = strength;
554 }
555 
556 
569 static int
571  const struct GNUNET_PeerIdentity *pid,
572  void *value)
573 {
574  (void)cls;
575  (void)value;
576  try_connect(pid,
577  NULL);
578  return GNUNET_YES;
579 }
580 
581 
588 static void
590 {
591  GNUNET_CONTAINER_multipeermap_iterate(all_desired_peers,
593  NULL);
594 }
595 
596 
606 static int
608  const struct GNUNET_PeerIdentity *key,
609  void *value)
610 {
611  struct GNUNET_BLOCK_Group *bg = cls;
612  struct GNUNET_HashCode key_hash;
613 
614  (void)cls;
615  (void)value;
616  GNUNET_CRYPTO_hash(key,
617  sizeof(struct GNUNET_PeerIdentity),
618  &key_hash);
620  &key_hash,
621  1);
623  "Adding known peer (%s) to bloomfilter for FIND PEER\n",
624  GNUNET_i2s(key));
625  return GNUNET_YES;
626 }
627 
628 
636 static void
638 {
639  struct GNUNET_TIME_Relative next_send_time;
640  struct GNUNET_BLOCK_Group *bg;
641  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
642 
643  (void)cls;
644  find_peer_task = NULL;
646  {
647  /* If we are finding many peers already, no need to send out our request right now! */
648  find_peer_task =
651  NULL);
652  newly_found_peers = 0;
653  return;
654  }
658  UINT32_MAX),
659  NULL,
660  0,
661  "filter-size",
663  NULL);
664  GNUNET_CONTAINER_multipeermap_iterate(all_connected_peers,
666  bg);
668  gettext_noop("# FIND PEER messages initiated"),
669  1,
670  GNUNET_NO);
671  peer_bf
675  // FIXME: pass priority!?
679  0,
681  NULL,
682  0,
683  bg,
684  peer_bf);
687  /* schedule next round */
688  next_send_time.rel_value_us =
689  DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us +
691  DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us /
692  (newly_found_peers + 1));
693  newly_found_peers = 0;
694  GNUNET_assert(NULL == find_peer_task);
695  find_peer_task =
696  GNUNET_SCHEDULER_add_delayed(next_send_time,
698  NULL);
699 }
700 
701 
710 static void *
712  const struct GNUNET_PeerIdentity *peer,
713  struct GNUNET_MQ_Handle *mq)
714 {
715  struct PeerInfo *pi;
716 
717  (void)cls;
718  /* Check for connect to self message */
719  if (0 == GNUNET_memcmp(&my_identity,
720  peer))
721  return NULL;
723  "Connected to %s\n",
724  GNUNET_i2s(peer));
726  GNUNET_CONTAINER_multipeermap_get(all_connected_peers,
727  peer));
729  gettext_noop("# peers connected"),
730  1,
731  GNUNET_NO);
732  pi = GNUNET_new(struct PeerInfo);
733  pi->id = peer;
734  pi->mq = mq;
735  GNUNET_CRYPTO_hash(peer,
736  sizeof(struct GNUNET_PeerIdentity),
737  &pi->phash);
738  pi->peer_bucket = find_bucket(&pi->phash);
739  GNUNET_assert((pi->peer_bucket >= 0) &&
740  ((unsigned int)pi->peer_bucket < MAX_BUCKETS));
743  pi);
746  (unsigned int)pi->peer_bucket);
748  GNUNET_CONTAINER_multipeermap_put(all_connected_peers,
749  pi->id,
750  pi,
752  if ((pi->peer_bucket > 0) &&
754  {
757  }
758  if ((1 == GNUNET_CONTAINER_multipeermap_size(all_connected_peers)) &&
760  {
761  /* got a first connection, good time to start with FIND PEER requests... */
762  GNUNET_assert(NULL == find_peer_task);
764  NULL);
765  }
766  return pi;
767 }
768 
769 
777 static void
779  const struct GNUNET_PeerIdentity *peer,
780  void *internal_cls)
781 {
782  struct PeerInfo *to_remove = internal_cls;
783 
784  (void)cls;
785  /* Check for disconnect from self message */
786  if (NULL == to_remove)
787  return;
789  "Disconnected %s\n",
790  GNUNET_i2s(peer));
792  gettext_noop("# peers connected"),
793  -1,
794  GNUNET_NO);
796  GNUNET_CONTAINER_multipeermap_remove(all_connected_peers,
797  peer,
798  to_remove));
799  if ((0 == GNUNET_CONTAINER_multipeermap_size(all_connected_peers)) &&
801  {
802  GNUNET_SCHEDULER_cancel(find_peer_task);
803  find_peer_task = NULL;
804  }
805  GNUNET_assert(to_remove->peer_bucket >= 0);
807  k_buckets[to_remove->peer_bucket].tail,
808  to_remove);
810  k_buckets[to_remove->peer_bucket].peers_size--;
811  while ((closest_bucket > 0) &&
812  (0 == k_buckets[to_remove->peer_bucket].peers_size))
813  closest_bucket--;
814  if (k_buckets[to_remove->peer_bucket].peers_size < bucket_size)
816  GNUNET_free(to_remove);
817 }
818 
819 
828 static unsigned int
830  uint32_t target_replication)
831 {
832  uint32_t random_value;
833  uint32_t forward_count;
834  float target_value;
835 
836  if (hop_count > GDS_NSE_get() * 4.0)
837  {
838  /* forcefully terminate */
840  gettext_noop("# requests TTL-dropped"),
841  1, GNUNET_NO);
842  return 0;
843  }
844  if (hop_count > GDS_NSE_get() * 2.0)
845  {
846  /* Once we have reached our ideal number of hops, only forward to 1 peer */
847  return 1;
848  }
849  /* bound by system-wide maximum */
850  target_replication =
851  GNUNET_MIN(MAXIMUM_REPLICATION_LEVEL, target_replication);
852  target_value =
853  1 + (target_replication - 1.0) / (GDS_NSE_get() +
854  ((float)(target_replication - 1.0) *
855  hop_count));
856  /* Set forward count to floor of target_value */
857  forward_count = (uint32_t)target_value;
858  /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
859  target_value = target_value - forward_count;
860  random_value =
862  if (random_value < (target_value * UINT32_MAX))
863  forward_count++;
864  return forward_count;
865 }
866 
867 
879 static unsigned int
880 get_distance(const struct GNUNET_HashCode *target,
881  const struct GNUNET_HashCode *have)
882 {
883  unsigned int bucket;
884  unsigned int msb;
885  unsigned int lsb;
886  unsigned int i;
887 
888  /* We have to represent the distance between two 2^9 (=512)-bit
889  * numbers as a 2^5 (=32)-bit number with "0" being used for the
890  * two numbers being identical; furthermore, we need to
891  * guarantee that a difference in the number of matching
892  * bits is always represented in the result.
893  *
894  * We use 2^32/2^9 numerical values to distinguish between
895  * hash codes that have the same LSB bit distance and
896  * use the highest 2^9 bits of the result to signify the
897  * number of (mis)matching LSB bits; if we have 0 matching
898  * and hence 512 mismatching LSB bits we return -1 (since
899  * 512 itself cannot be represented with 9 bits) */
900 
901  /* first, calculate the most significant 9 bits of our
902  * result, aka the number of LSBs */
903  bucket = GNUNET_CRYPTO_hash_matching_bits(target,
904  have);
905  /* bucket is now a value between 0 and 512 */
906  if (bucket == 512)
907  return 0; /* perfect match */
908  if (bucket == 0)
909  return (unsigned int)-1; /* LSB differs; use max (if we did the bit-shifting
910  * below, we'd end up with max+1 (overflow)) */
911 
912  /* calculate the most significant bits of the final result */
913  msb = (512 - bucket) << (32 - 9);
914  /* calculate the 32-9 least significant bits of the final result by
915  * looking at the differences in the 32-9 bits following the
916  * mismatching bit at 'bucket' */
917  lsb = 0;
918  for (i = bucket + 1;
919  (i < sizeof(struct GNUNET_HashCode) * 8) && (i < bucket + 1 + 32 - 9); i++)
920  {
921  if (GNUNET_CRYPTO_hash_get_bit(target, i) !=
923  lsb |= (1 << (bucket + 32 - 9 - i)); /* first bit set will be 10,
924  * last bit set will be 31 -- if
925  * i does not reach 512 first... */
926  }
927  return msb | lsb;
928 }
929 
930 
941 int
943  const struct GNUNET_CONTAINER_BloomFilter *bloom)
944 {
945  int bits;
946  int other_bits;
947  int bucket_num;
948  struct PeerInfo *pos;
949 
951  key))
952  return GNUNET_YES;
953  bucket_num = find_bucket(key);
954  GNUNET_assert(bucket_num >= 0);
956  key);
957  pos = k_buckets[bucket_num].head;
958  while (NULL != pos)
959  {
960  if ((NULL != bloom) &&
961  (GNUNET_YES ==
963  &pos->phash)))
964  {
965  pos = pos->next;
966  continue; /* Skip already checked entries */
967  }
968  other_bits = GNUNET_CRYPTO_hash_matching_bits(&pos->phash,
969  key);
970  if (other_bits > bits)
971  return GNUNET_NO;
972  if (other_bits == bits) /* We match the same number of bits */
973  return GNUNET_YES;
974  pos = pos->next;
975  }
976  /* No peers closer, we are the closest! */
977  return GNUNET_YES;
978 }
979 
980 
998 static struct PeerInfo *
999 select_peer(const struct GNUNET_HashCode *key,
1000  const struct GNUNET_CONTAINER_BloomFilter *bloom,
1001  uint32_t hops)
1002 {
1003  unsigned int bc;
1004  unsigned int count;
1005  unsigned int selected;
1006  struct PeerInfo *pos;
1007  unsigned int dist;
1008  unsigned int smallest_distance;
1009  struct PeerInfo *chosen;
1010 
1011  if (hops >= GDS_NSE_get())
1012  {
1013  /* greedy selection (closest peer that is not in bloomfilter) */
1014  smallest_distance = UINT_MAX;
1015  chosen = NULL;
1016  for (bc = 0; bc <= closest_bucket; bc++)
1017  {
1018  pos = k_buckets[bc].head;
1019  count = 0;
1020  while ((pos != NULL) && (count < bucket_size))
1021  {
1022  if ((NULL == bloom) ||
1023  (GNUNET_NO ==
1025  &pos->phash)))
1026  {
1027  dist = get_distance(key,
1028  &pos->phash);
1029  if (dist < smallest_distance)
1030  {
1031  chosen = pos;
1032  smallest_distance = dist;
1033  }
1034  }
1035  else
1036  {
1038  "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1039  GNUNET_i2s(pos->id),
1040  GNUNET_h2s(key));
1042  gettext_noop("# Peers excluded from routing due to Bloomfilter"),
1043  1,
1044  GNUNET_NO);
1045  dist = get_distance(key,
1046  &pos->phash);
1047  if (dist < smallest_distance)
1048  {
1049  chosen = NULL;
1050  smallest_distance = dist;
1051  }
1052  }
1053  count++;
1054  pos = pos->next;
1055  }
1056  }
1057  if (NULL == chosen)
1059  gettext_noop("# Peer selection failed"),
1060  1,
1061  GNUNET_NO);
1062  else
1064  "Selected peer `%s' in greedy routing for %s\n",
1065  GNUNET_i2s(chosen->id),
1066  GNUNET_h2s(key));
1067  return chosen;
1068  }
1069 
1070  /* select "random" peer */
1071  /* count number of peers that are available and not filtered */
1072  count = 0;
1073  for (bc = 0; bc <= closest_bucket; bc++)
1074  {
1075  pos = k_buckets[bc].head;
1076  while ((NULL != pos) && (count < bucket_size))
1077  {
1078  if ((NULL != bloom) &&
1079  (GNUNET_YES ==
1081  &pos->phash)))
1082  {
1084  gettext_noop
1085  ("# Peers excluded from routing due to Bloomfilter"),
1086  1, GNUNET_NO);
1088  "Excluded peer `%s' due to BF match in random routing for %s\n",
1089  GNUNET_i2s(pos->id),
1090  GNUNET_h2s(key));
1091  pos = pos->next;
1092  continue; /* Ignore bloomfiltered peers */
1093  }
1094  count++;
1095  pos = pos->next;
1096  }
1097  }
1098  if (0 == count) /* No peers to select from! */
1099  {
1101  gettext_noop("# Peer selection failed"), 1,
1102  GNUNET_NO);
1103  return NULL;
1104  }
1105  /* Now actually choose a peer */
1107  count);
1108  count = 0;
1109  for (bc = 0; bc <= closest_bucket; bc++)
1110  {
1111  for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size)); pos = pos->next)
1112  {
1113  if ((bloom != NULL) &&
1114  (GNUNET_YES ==
1116  &pos->phash)))
1117  {
1118  continue; /* Ignore bloomfiltered peers */
1119  }
1120  if (0 == selected--)
1121  {
1123  "Selected peer `%s' in random routing for %s\n",
1124  GNUNET_i2s(pos->id),
1125  GNUNET_h2s(key));
1126  return pos;
1127  }
1128  }
1129  }
1130  GNUNET_break(0);
1131  return NULL;
1132 }
1133 
1134 
1148 static unsigned int
1150  struct GNUNET_CONTAINER_BloomFilter *bloom,
1151  uint32_t hop_count,
1152  uint32_t target_replication,
1153  struct PeerInfo ***targets)
1154 {
1155  unsigned int ret;
1156  unsigned int off;
1157  struct PeerInfo **rtargets;
1158  struct PeerInfo *nxt;
1159 
1160  GNUNET_assert(NULL != bloom);
1161  ret = get_forward_count(hop_count,
1162  target_replication);
1163  if (0 == ret)
1164  {
1165  *targets = NULL;
1166  return 0;
1167  }
1168  rtargets = GNUNET_new_array(ret,
1169  struct PeerInfo *);
1170  for (off = 0; off < ret; off++)
1171  {
1172  nxt = select_peer(key,
1173  bloom,
1174  hop_count);
1175  if (NULL == nxt)
1176  break;
1177  rtargets[off] = nxt;
1180  &nxt->phash));
1182  &nxt->phash);
1183  }
1185  "Selected %u/%u peers at hop %u for %s (target was %u)\n",
1186  off,
1187  GNUNET_CONTAINER_multipeermap_size(all_connected_peers),
1188  (unsigned int)hop_count,
1189  GNUNET_h2s(key),
1190  ret);
1191  if (0 == off)
1192  {
1193  GNUNET_free(rtargets);
1194  *targets = NULL;
1195  return 0;
1196  }
1197  *targets = rtargets;
1199  "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1200  GNUNET_h2s(key),
1201  off,
1202  ret);
1203  return off;
1204 }
1205 
1206 
1227 int
1230  uint32_t desired_replication_level,
1232  uint32_t hop_count,
1233  struct GNUNET_CONTAINER_BloomFilter *bf,
1234  const struct GNUNET_HashCode *key,
1235  unsigned int put_path_length,
1236  struct GNUNET_PeerIdentity *put_path,
1237  const void *data,
1238  size_t data_size)
1239 {
1240  unsigned int target_count;
1241  unsigned int i;
1242  struct PeerInfo **targets;
1243  struct PeerInfo *target;
1244  size_t msize;
1245  struct GNUNET_MQ_Envelope *env;
1246  struct PeerPutMessage *ppm;
1247  struct GNUNET_PeerIdentity *pp;
1248  unsigned int skip_count;
1249 
1250  GNUNET_assert(NULL != bf);
1252  "Adding myself (%s) to PUT bloomfilter for %s\n",
1254  GNUNET_h2s(key));
1256  &my_identity_hash);
1258  gettext_noop("# PUT requests routed"),
1259  1,
1260  GNUNET_NO);
1261  target_count
1262  = get_target_peers(key,
1263  bf,
1264  hop_count,
1265  desired_replication_level,
1266  &targets);
1267  if (0 == target_count)
1268  {
1270  "Routing PUT for %s terminates after %u hops at %s\n",
1271  GNUNET_h2s(key),
1272  (unsigned int)hop_count,
1274  return GNUNET_NO;
1275  }
1276  msize = put_path_length * sizeof(struct GNUNET_PeerIdentity) + data_size;
1277  if (msize + sizeof(struct PeerPutMessage)
1279  {
1280  put_path_length = 0;
1281  msize = data_size;
1282  }
1283  if (msize + sizeof(struct PeerPutMessage)
1285  {
1286  GNUNET_break(0);
1287  GNUNET_free(targets);
1288  return GNUNET_NO;
1289  }
1291  gettext_noop("# PUT messages queued for transmission"),
1292  target_count,
1293  GNUNET_NO);
1294  skip_count = 0;
1295  for (i = 0; i < target_count; i++)
1296  {
1297  target = targets[i];
1299  {
1300  /* skip */
1302  gettext_noop("# P2P messages dropped due to full queue"),
1303  1,
1304  GNUNET_NO);
1305  skip_count++;
1306  continue;
1307  }
1309  "Routing PUT for %s after %u hops to %s\n",
1310  GNUNET_h2s(key),
1311  (unsigned int)hop_count,
1312  GNUNET_i2s(target->id));
1313  env = GNUNET_MQ_msg_extra(ppm,
1314  msize,
1316  ppm->options = htonl(options);
1317  ppm->type = htonl(type);
1318  ppm->hop_count = htonl(hop_count + 1);
1319  ppm->desired_replication_level = htonl(desired_replication_level);
1320  ppm->put_path_length = htonl(put_path_length);
1321  ppm->expiration_time = GNUNET_TIME_absolute_hton(expiration_time);
1324  &target->phash));
1327  ppm->bloomfilter,
1328  DHT_BLOOM_SIZE));
1329  ppm->key = *key;
1330  pp = (struct GNUNET_PeerIdentity *)&ppm[1];
1331  GNUNET_memcpy(pp,
1332  put_path,
1333  sizeof(struct GNUNET_PeerIdentity) * put_path_length);
1334  GNUNET_memcpy(&pp[put_path_length],
1335  data,
1336  data_size);
1337  GNUNET_MQ_send(target->mq,
1338  env);
1339  }
1340  GNUNET_free(targets);
1341  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1342 }
1343 
1344 
1362 int
1365  uint32_t desired_replication_level,
1366  uint32_t hop_count,
1367  const struct GNUNET_HashCode *key,
1368  const void *xquery,
1369  size_t xquery_size,
1370  struct GNUNET_BLOCK_Group *bg,
1371  struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1372 {
1373  unsigned int target_count;
1374  struct PeerInfo **targets;
1375  struct PeerInfo *target;
1376  struct GNUNET_MQ_Envelope *env;
1377  size_t msize;
1378  struct PeerGetMessage *pgm;
1379  char *xq;
1380  size_t reply_bf_size;
1381  void *reply_bf;
1382  unsigned int skip_count;
1383  uint32_t bf_nonce;
1384 
1385  GNUNET_assert(NULL != peer_bf);
1387  gettext_noop("# GET requests routed"),
1388  1,
1389  GNUNET_NO);
1390  target_count = get_target_peers(key,
1391  peer_bf,
1392  hop_count,
1393  desired_replication_level,
1394  &targets);
1396  "Adding myself (%s) to GET bloomfilter for %s\n",
1398  GNUNET_h2s(key));
1400  &my_identity_hash);
1401  if (0 == target_count)
1402  {
1404  "Routing GET for %s terminates after %u hops at %s\n",
1405  GNUNET_h2s(key),
1406  (unsigned int)hop_count,
1408  return GNUNET_NO;
1409  }
1410  if (GNUNET_OK !=
1412  &bf_nonce,
1413  &reply_bf,
1414  &reply_bf_size))
1415  {
1416  reply_bf = NULL;
1417  reply_bf_size = 0;
1419  UINT32_MAX);
1420  }
1421  msize = xquery_size + reply_bf_size;
1422  if (msize + sizeof(struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
1423  {
1424  GNUNET_break(0);
1425  GNUNET_free_non_null(reply_bf);
1426  GNUNET_free(targets);
1427  return GNUNET_NO;
1428  }
1430  gettext_noop("# GET messages queued for transmission"),
1431  target_count,
1432  GNUNET_NO);
1433  /* forward request */
1434  skip_count = 0;
1435  for (unsigned int i = 0; i < target_count; i++)
1436  {
1437  target = targets[i];
1439  {
1440  /* skip */
1442  gettext_noop("# P2P messages dropped due to full queue"),
1443  1, GNUNET_NO);
1444  skip_count++;
1445  continue;
1446  }
1448  "Routing GET for %s after %u hops to %s\n",
1449  GNUNET_h2s(key),
1450  (unsigned int)hop_count,
1451  GNUNET_i2s(target->id));
1452  env = GNUNET_MQ_msg_extra(pgm,
1453  msize,
1455  pgm->options = htonl(options);
1456  pgm->type = htonl(type);
1457  pgm->hop_count = htonl(hop_count + 1);
1458  pgm->desired_replication_level = htonl(desired_replication_level);
1459  pgm->xquery_size = htonl(xquery_size);
1460  pgm->bf_mutator = bf_nonce;
1463  &target->phash));
1466  pgm->bloomfilter,
1467  DHT_BLOOM_SIZE));
1468  pgm->key = *key;
1469  xq = (char *)&pgm[1];
1470  GNUNET_memcpy(xq,
1471  xquery,
1472  xquery_size);
1473  GNUNET_memcpy(&xq[xquery_size],
1474  reply_bf,
1475  reply_bf_size);
1476  GNUNET_MQ_send(target->mq,
1477  env);
1478  }
1479  GNUNET_free(targets);
1480  GNUNET_free_non_null(reply_bf);
1481  return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1482 }
1483 
1484 
1501 void
1503  enum GNUNET_BLOCK_Type type,
1505  const struct GNUNET_HashCode *key,
1506  unsigned int put_path_length,
1507  const struct GNUNET_PeerIdentity *put_path,
1508  unsigned int get_path_length,
1509  const struct GNUNET_PeerIdentity *get_path,
1510  const void *data,
1511  size_t data_size)
1512 {
1513  struct PeerInfo *pi;
1514  struct GNUNET_MQ_Envelope *env;
1515  size_t msize;
1516  struct PeerResultMessage *prm;
1517  struct GNUNET_PeerIdentity *paths;
1518 
1519  msize = data_size + (get_path_length + put_path_length) *
1520  sizeof(struct GNUNET_PeerIdentity);
1521  if ((msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
1522  (get_path_length >
1523  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1524  (put_path_length >
1525  GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1526  (data_size > GNUNET_MAX_MESSAGE_SIZE))
1527  {
1528  GNUNET_break(0);
1529  return;
1530  }
1531  pi = GNUNET_CONTAINER_multipeermap_get(all_connected_peers,
1532  target);
1533  if (NULL == pi)
1534  {
1535  /* peer disconnected in the meantime, drop reply */
1537  "No matching peer for reply for key %s\n",
1538  GNUNET_h2s(key));
1539  return;
1540  }
1542  {
1543  /* skip */
1545  gettext_noop("# 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;
1600  GNUNET_CRYPTO_hash(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 */
1815  if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
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(put->desired_replication_level),
1828  exp_time,
1829  ntohl(put->hop_count),
1830  bf,
1831  &put->key,
1832  putlen,
1833  pp,
1834  payload,
1835  payload_size);
1836  /* notify monitoring clients */
1837  GDS_CLIENTS_process_put(options
1838  | ((GNUNET_OK == forwarded)
1840  : 0),
1841  ntohl(put->type),
1842  ntohl(put->hop_count),
1843  ntohl(put->desired_replication_level),
1844  putlen, pp,
1845  exp_time,
1846  &put->key,
1847  payload,
1848  payload_size);
1849  }
1851 }
1852 
1853 
1862 static void
1864  const struct GNUNET_HashCode *key,
1865  struct GNUNET_BLOCK_Group *bg)
1866 {
1867  int bucket_idx;
1868  struct PeerBucket *bucket;
1869  struct PeerInfo *peer;
1870  unsigned int choice;
1871  const struct GNUNET_HELLO_Message *hello;
1872  size_t hello_size;
1873 
1874  /* first, check about our own HELLO */
1875  if (NULL != GDS_my_hello)
1876  {
1877  hello_size = GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)GDS_my_hello);
1878  GNUNET_break(hello_size >= sizeof(struct GNUNET_MessageHeader));
1882  bg,
1885  NULL, 0,
1886  GDS_my_hello,
1887  hello_size))
1888  {
1892  key,
1893  0,
1894  NULL,
1895  0,
1896  NULL,
1897  GDS_my_hello,
1898  hello_size);
1899  }
1900  else
1901  {
1903  gettext_noop("# FIND PEER requests ignored due to Bloomfilter"),
1904  1,
1905  GNUNET_NO);
1906  }
1907  }
1908  else
1909  {
1911  gettext_noop("# FIND PEER requests ignored due to lack of HELLO"),
1912  1,
1913  GNUNET_NO);
1914  }
1915 
1916  /* then, also consider sending a random HELLO from the closest bucket */
1917  if (0 == memcmp(&my_identity_hash,
1918  key,
1919  sizeof(struct GNUNET_HashCode)))
1920  bucket_idx = closest_bucket;
1921  else
1922  bucket_idx = GNUNET_MIN((int)closest_bucket,
1923  find_bucket(key));
1924  if (bucket_idx < 0)
1925  return;
1926  bucket = &k_buckets[bucket_idx];
1927  if (bucket->peers_size == 0)
1928  return;
1930  bucket->peers_size);
1931  peer = bucket->head;
1932  while (choice > 0)
1933  {
1934  GNUNET_assert(NULL != peer);
1935  peer = peer->next;
1936  choice--;
1937  }
1938  choice = bucket->peers_size;
1939  do
1940  {
1941  peer = peer->next;
1942  if (0 == choice--)
1943  return; /* no non-masked peer available */
1944  if (NULL == peer)
1945  peer = bucket->head;
1946  hello = GDS_HELLO_get(peer->id);
1947  }
1948  while ((NULL == hello) ||
1952  bg,
1954  &peer->phash,
1955  NULL, 0,
1956  hello,
1957  (hello_size = GNUNET_HELLO_size(hello)))));
1962  key,
1963  0,
1964  NULL,
1965  0,
1966  NULL,
1967  hello,
1968  hello_size);
1969 }
1970 
1971 
1986 static void
1988  enum GNUNET_BLOCK_Type type,
1990  const struct GNUNET_HashCode *key,
1991  unsigned int put_path_length,
1992  const struct GNUNET_PeerIdentity *put_path,
1993  unsigned int get_path_length,
1994  const struct GNUNET_PeerIdentity *get_path,
1995  const void *data,
1996  size_t data_size)
1997 {
1998  struct PeerInfo *peer = cls;
1999  char *pp;
2000 
2001  pp = GNUNET_STRINGS_pp2s(put_path,
2002  put_path_length);
2004  "Found local result for %s (PP: %s)\n",
2005  GNUNET_h2s(key),
2006  pp);
2007  GNUNET_free(pp);
2009  type,
2010  expiration_time,
2011  key,
2012  put_path_length, put_path,
2013  get_path_length, get_path,
2014  data, data_size);
2015 }
2016 
2017 
2025 static int
2027  const struct PeerGetMessage *get)
2028 {
2029  uint32_t xquery_size;
2030  uint16_t msize;
2031 
2032  (void)cls;
2033  msize = ntohs(get->header.size);
2034  xquery_size = ntohl(get->xquery_size);
2035  if (msize < sizeof(struct PeerGetMessage) + xquery_size)
2036  {
2037  GNUNET_break_op(0);
2038  return GNUNET_SYSERR;
2039  }
2040  return GNUNET_OK;
2041 }
2042 
2043 
2050 static void
2052  const struct PeerGetMessage *get)
2053 {
2054  struct PeerInfo *peer = cls;
2055  uint32_t xquery_size;
2056  size_t reply_bf_size;
2057  uint16_t msize;
2058  enum GNUNET_BLOCK_Type type;
2061  struct GNUNET_BLOCK_Group *bg;
2062  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2063  const char *xquery;
2064  int forwarded;
2065 
2066  /* parse and validate message */
2067  msize = ntohs(get->header.size);
2068  xquery_size = ntohl(get->xquery_size);
2069  reply_bf_size = msize - (sizeof(struct PeerGetMessage) + xquery_size);
2070  type = ntohl(get->type);
2071  options = ntohl(get->options);
2072  xquery = (const char *)&get[1];
2074  gettext_noop("# P2P GET requests received"),
2075  1,
2076  GNUNET_NO);
2078  gettext_noop("# P2P GET bytes received"),
2079  msize,
2080  GNUNET_NO);
2082  {
2083  char *tmp;
2084 
2087  "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
2088  GNUNET_h2s(&get->key),
2089  GNUNET_i2s(peer->id),
2090  tmp,
2091  ntohl(get->hop_count),
2093  &get->key),
2095  &get->key),
2096  ntohl(get->xquery_size),
2097  xquery);
2098  GNUNET_free(tmp);
2099  }
2100  eval
2102  type,
2103  NULL,
2105  &get->key,
2106  xquery,
2107  xquery_size,
2108  NULL,
2109  0);
2111  {
2112  /* request invalid or block type not supported */
2114  return;
2115  }
2116  peer_bf = GNUNET_CONTAINER_bloomfilter_init(get->bloomfilter,
2121  &peer->phash));
2123  type,
2124  get->bf_mutator,
2125  &xquery[xquery_size],
2126  reply_bf_size,
2127  "filter-size",
2128  reply_bf_size,
2129  NULL);
2131  "GET for %s at %s after %u hops\n",
2132  GNUNET_h2s(&get->key),
2134  (unsigned int)ntohl(get->hop_count));
2135  /* local lookup (this may update the reply_bf) */
2136  if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2137  (GDS_am_closest_peer(&get->key,
2138  peer_bf)))
2139  {
2140  if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
2141  {
2143  gettext_noop("# P2P FIND PEER requests processed"),
2144  1,
2145  GNUNET_NO);
2146  handle_find_peer(peer->id,
2147  &get->key,
2148  bg);
2149  }
2150  else
2151  {
2152  eval = GDS_DATACACHE_handle_get(&get->key,
2153  type,
2154  xquery,
2155  xquery_size,
2156  bg,
2158  peer);
2159  }
2160  }
2161  else
2162  {
2164  gettext_noop("# P2P GET requests ONLY routed"),
2165  1,
2166  GNUNET_NO);
2167  }
2168 
2169  /* remember request for routing replies */
2170  GDS_ROUTING_add(peer->id,
2171  type,
2172  bg, /* bg now owned by routing, but valid at least until end of this function! */
2173  options,
2174  &get->key,
2175  xquery,
2176  xquery_size);
2177 
2178  /* P2P forwarding */
2179  forwarded = GNUNET_NO;
2180  if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
2181  forwarded = GDS_NEIGHBOURS_handle_get(type,
2182  options,
2183  ntohl(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 GNUNET_PeerIdentity));
2357  gettext_noop("# P2P RESULTS received"),
2358  1,
2359  GNUNET_NO);
2361  gettext_noop("# P2P RESULT bytes received"),
2362  msize,
2363  GNUNET_NO);
2365  {
2366  char *tmp;
2367  char *pp;
2368  char *gp;
2369 
2370  gp = GNUNET_STRINGS_pp2s(get_path,
2371  get_path_length);
2372  pp = GNUNET_STRINGS_pp2s(put_path,
2373  put_path_length);
2376  "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n",
2377  GNUNET_h2s(&prm->key),
2378  GNUNET_i2s(peer->id),
2379  tmp,
2380  gp,
2381  pp);
2382  GNUNET_free(gp);
2383  GNUNET_free(pp);
2384  GNUNET_free(tmp);
2385  }
2386  /* if we got a HELLO, consider it for our own routing table */
2387  if (GNUNET_BLOCK_TYPE_DHT_HELLO == type)
2388  {
2389  const struct GNUNET_MessageHeader *h;
2390  struct GNUNET_PeerIdentity pid;
2391 
2392  /* Should be a HELLO, validate and consider using it! */
2393  if (data_size < sizeof(struct GNUNET_HELLO_Message))
2394  {
2395  GNUNET_break_op(0);
2396  return;
2397  }
2398  h = data;
2399  if (data_size != ntohs(h->size))
2400  {
2401  GNUNET_break_op(0);
2402  return;
2403  }
2404  if (GNUNET_OK !=
2405  GNUNET_HELLO_get_id((const struct GNUNET_HELLO_Message *)h,
2406  &pid))
2407  {
2408  GNUNET_break_op(0);
2409  return;
2410  }
2411  if ((GNUNET_YES != disable_try_connect) &&
2412  (0 != memcmp(&my_identity,
2413  &pid,
2414  sizeof(struct GNUNET_PeerIdentity))))
2415  try_connect(&pid,
2416  h);
2417  }
2418 
2419  /* First, check if 'peer' is already on the path, and if
2420  so, truncate it instead of expanding. */
2421  for (unsigned int i = 0; i <= get_path_length; i++)
2422  if (0 == memcmp(&get_path[i],
2423  peer->id,
2424  sizeof(struct GNUNET_PeerIdentity)))
2425  {
2426  process_reply_with_path(exp_time,
2427  &prm->key,
2428  i,
2429  get_path,
2430  put_path_length,
2431  put_path,
2432  type,
2433  data_size,
2434  data);
2435  return;
2436  }
2437 
2438  /* Need to append 'peer' to 'get_path' (normal case) */
2439  {
2440  struct GNUNET_PeerIdentity xget_path[get_path_length + 1];
2441 
2442  GNUNET_memcpy(xget_path,
2443  get_path,
2444  get_path_length * sizeof(struct GNUNET_PeerIdentity));
2445  xget_path[get_path_length] = *peer->id;
2446 
2447  process_reply_with_path(exp_time,
2448  &prm->key,
2449  get_path_length + 1,
2450  xget_path,
2451  put_path_length,
2452  put_path,
2453  type,
2454  data_size,
2455  data);
2456  }
2457 }
2458 
2459 
2465 int
2467 {
2468  struct GNUNET_MQ_MessageHandler core_handlers[] = {
2469  GNUNET_MQ_hd_var_size(dht_p2p_get,
2471  struct PeerGetMessage,
2472  NULL),
2473  GNUNET_MQ_hd_var_size(dht_p2p_put,
2475  struct PeerPutMessage,
2476  NULL),
2477  GNUNET_MQ_hd_var_size(dht_p2p_result,
2479  struct PeerResultMessage,
2480  NULL),
2482  };
2483  unsigned long long temp_config_num;
2484 
2487  "DHT",
2488  "DISABLE_TRY_CONNECT");
2489  if (GNUNET_OK ==
2491  "DHT",
2492  "bucket_size",
2493  &temp_config_num))
2494  bucket_size = (unsigned int)temp_config_num;
2497  "DHT",
2498  "CACHE_RESULTS");
2499 
2501  (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO;
2503  core_api = GNUNET_CORE_connect(GDS_cfg,
2504  NULL,
2505  &core_init,
2508  core_handlers);
2509  if (NULL == core_api)
2510  return GNUNET_SYSERR;
2511  all_connected_peers = GNUNET_CONTAINER_multipeermap_create(256,
2512  GNUNET_YES);
2513  all_desired_peers = GNUNET_CONTAINER_multipeermap_create(256,
2514  GNUNET_NO);
2515  return GNUNET_OK;
2516 }
2517 
2518 
2522 void
2524 {
2525  if (NULL == core_api)
2526  return;
2527  GNUNET_CORE_disconnect(core_api);
2528  core_api = NULL;
2529  GNUNET_assert(0 ==
2530  GNUNET_CONTAINER_multipeermap_size(all_connected_peers));
2531  GNUNET_CONTAINER_multipeermap_destroy(all_connected_peers);
2532  all_connected_peers = NULL;
2533  GNUNET_CONTAINER_multipeermap_iterate(all_desired_peers,
2535  NULL);
2536  GNUNET_CONTAINER_multipeermap_destroy(all_desired_peers);
2537  all_desired_peers = NULL;
2539  ats_ch = NULL;
2540  GNUNET_assert(NULL == find_peer_task);
2541 }
2542 
2543 
2549 struct GNUNET_PeerIdentity *
2551 {
2552  return &my_identity;
2553 }
2554 
2555 
2556 /* 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:662
uint32_t type
Content type.
static unsigned int get_distance(const struct GNUNET_HashCode *target, const struct GNUNET_HashCode *have)
Compute the distance between have and target as a 32-bit value.
struct GNUNET_MessageHeader * GDS_my_hello
Our HELLO.
GNUnet DHT globals.
uint32_t type
Desired content type.
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
We should keep track of the route that the message took in the P2P network.
A HELLO message is used to exchange information about transports with other peers.
#define DHT_MINIMUM_FIND_PEER_INTERVAL
How long at least to wait before sending another find peer request.
static struct PeerBucket k_buckets[sizeof(struct GNUNET_HashCode) *8]
The buckets.
Entry in linked list for all offer-HELLO requests.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:671
struct PeerInfo * prev
Prev peer entry (DLL)
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
static int cache_results
Do we cache all results that we are routing in the local datacache?
uint64_t rel_value_us
The actual value.
static struct PeerInfo * select_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops)
Select a peer from the routing table that would be a good routing destination for sending a message f...
uint32_t put_path_length
Length of the PUT path that follows (if tracked).
struct PeerInfo * next
Next peer entry (DLL)
uint32_t hop_count
Hop count.
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2185
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:76
#define MAXIMUM_PENDING_PER_PEER
Maximum allowed number of pending messages per peer.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
static void update_connect_preferences()
Update our preferences for connectivity as given to ATS.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
#define GNUNET_TIME_UNIT_MINUTES
One minute.
static void handle_dht_p2p_get(void *cls, const struct PeerGetMessage *get)
Core handler for p2p get requests.
unsigned int GNUNET_CRYPTO_hash_matching_bits(const struct GNUNET_HashCode *first, const struct GNUNET_HashCode *second)
Determine how many low order bits match in two struct GNUNET_HashCodes.
Definition: crypto_hash.c:256
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
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.
Block does not match xquery (valid result, not relevant for the request)
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
uint32_t get_path_length
Length of the GET path that follows (if tracked).
#define GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION
After how long do we expire an address in a HELLO that we just validated? This value is also used for...
unsigned int peers_size
Number of peers in the bucket.
#define GNUNET_NO
Definition: gnunet_common.h:78
static unsigned int get_forward_count(uint32_t hop_count, uint32_t target_replication)
To how many peers should we (on average) forward the request to obtain the desired target_replication...
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
struct GNUNET_HashCode phash
Hash of id.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void core_init(void *cls, const struct GNUNET_PeerIdentity *identity)
To be called on core init/fail.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
uint32_t options
Processing options.
struct GNUNET_HashCode key
The key we are looking for.
Default behavior.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GDS_CLIENTS_process_get(uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode *key)
Check if some client is monitoring GET messages and notify them in that case.
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
What is the maximum size for encrypted messages? Note that this number imposes a clear limit on the m...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
GNUnet DHT integration with peerinfo.
void GDS_CLIENTS_process_put(uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const void *data, size_t size)
Check if some client is monitoring PUT messages and notify them in that case.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static unsigned int newly_found_peers
How many peers have we added since we sent out our last find peer request?
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
#define FIND_PEER_REPLICATION_LEVEL
Desired replication level for FIND PEER requests.
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_BLOCK_get_key(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key)
Function called to obtain the key for a block.
Definition: block.c:377
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:1237
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:44
Information about a peer that we would like to connect to.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:333
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
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:100
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:1264
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:337
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
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:179
GNUnet DHT tracking of requests for routing replies.
Internal representation of the hash map.
Type of a block that contains a HELLO for a peer (for DHT and CADET find-peer operations).
A 512-bit hashcode.
Message handler for a specific message type.
GNUNET_DHT_RouteOption
Options for routing.
uint32_t desired_replication_level
Replication level for this message.
void GNUNET_TRANSPORT_offer_hello_cancel(struct GNUNET_TRANSPORT_OfferHelloHandle *ohh)
Cancel the request to transport to offer the HELLO message.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_GET
Peer tries to find data in DHT.
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
void GDS_ROUTING_process(enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a reply (route to origin).
struct GNUNET_ATS_ConnectivitySuggestHandle * sh
Handle to active connectivity suggestion operation, or NULL.
The block is obtained from the local database, skip cryptographic checks.
Peers are grouped into buckets.
static void handle_local_result(void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a result from local datacache for a GET operation.
#define MAXIMUM_REPLICATION_LEVEL
Maximum allowed replication level for all requests.
uint32_t bf_mutator
Bloomfilter mutator.
Valid result, and there may be more.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int GNUNET_CRYPTO_hash_get_bit(const struct GNUNET_HashCode *code, unsigned int bit)
Obtain a bit from a hashcode.
Definition: crypto_hash.c:236
Entry for a peer in a bucket.
struct GNUNET_CORE_Handle * GNUNET_CORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, GNUNET_CORE_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Connect to the core service.
Definition: core_api.c:690
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:728
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:288
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:84
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:228
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:131
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:643
Block group data.
static struct GNUNET_ATS_ConnectivityHandle * ats_ch
Handle to ATS connectivity.
#define LOG_TRAFFIC(kind,...)
static void handle_core_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls)
Method called whenever a peer disconnects.
static unsigned int bucket_size
Maximum size for each bucket.
enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback gc, void *gc_cls)
Handle a GET request we&#39;ve received from another peer.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
static struct GNUNET_CONTAINER_MultiPeerMap * all_desired_peers
Hash map of all peers we would like to be connected to.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
void GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *bg, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size)
Add a new entry to our routing table.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:351
double GDS_NSE_get()
Return the log of the current network size estimate.
int GDS_NEIGHBOURS_init()
Initialize neighbours subsystem.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_MQ_Handle * mq
Handle for sending messages to this peer.
Block to store a cadet regex state.
static unsigned int get_target_peers(const struct GNUNET_HashCode *key, struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hop_count, uint32_t target_replication, struct PeerInfo ***targets)
Compute the set of peers that the given request should be forwarded to.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
Configuration we use.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint32_t data
The data value.
Handle to the ATS subsystem for connectivity management.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
Peer is storing data in DHT.
void GNUNET_ATS_connectivity_done(struct GNUNET_ATS_ConnectivityHandle *ch)
Client is done with ATS connectivity management, release resources.
static size_t data_size
Number of bytes in data.
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
struct GNUNET_HashCode key
The key of the corresponding GET request.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:655
Query is valid, no reply given.
void GDS_NEIGHBOURS_handle_reply(const struct GNUNET_PeerIdentity *target, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size)
Handle a reply (route to origin).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associcated with a filter in memory, flush to drive if needed (do not free the space o...
static void offer_hello_done(void *cls)
Function called when GNUNET_TRANSPORT_offer_hello() is done.
static void * handle_core_connect(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a peer connects.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
Each peer along the way should look at &#39;enc&#39; (otherwise only the k-peers closest to the key should lo...
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
GNUnet DHT integration with NSE.
void GDS_CLIENTS_handle_reply(struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data)
Handle a reply we&#39;ve received from another peer.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
Data is returned to peer from DHT.
Time for relative time used by GNUnet, in microseconds.
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition: block.c:204
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:408
#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:956
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.