aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-08-05 15:45:37 +0000
committerNathan S. Evans <evans@in.tum.de>2010-08-05 15:45:37 +0000
commitc59802b4a2aa41f3293121742eaacd8df295302c (patch)
treeb1514417abb26b66328eec964270aecee9c2d7b6 /src
parentf52b27f49550725feebd74567b5e014122d05369 (diff)
downloadgnunet-c59802b4a2aa41f3293121742eaacd8df295302c.tar.gz
gnunet-c59802b4a2aa41f3293121742eaacd8df295302c.zip
routing table changes, not stable
Diffstat (limited to 'src')
-rw-r--r--src/dht/gnunet-service-dht.c318
1 files changed, 241 insertions, 77 deletions
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index 1e2ba80a1..125bd7fff 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -41,12 +41,20 @@
41#include "dhtlog.h" 41#include "dhtlog.h"
42#include "dht.h" 42#include "dht.h"
43 43
44#define PRINT_TABLES GNUNET_NO
45
46#define EXTRA_CHECKS GNUNET_YES
44/** 47/**
45 * How many buckets will we allow total. 48 * How many buckets will we allow total.
46 */ 49 */
47#define MAX_BUCKETS sizeof (GNUNET_HashCode) * 8 50#define MAX_BUCKETS sizeof (GNUNET_HashCode) * 8
48 51
49/** 52/**
53 * Should the DHT issue FIND_PEER requests to get better routing tables?
54 */
55#define DO_FIND_PEER GNUNET_YES
56
57/**
50 * What is the maximum number of peers in a given bucket. 58 * What is the maximum number of peers in a given bucket.
51 */ 59 */
52#define DEFAULT_BUCKET_SIZE 8 60#define DEFAULT_BUCKET_SIZE 8
@@ -62,7 +70,7 @@
62 70
63#define DHT_DEFAULT_FIND_PEER_OPTIONS GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE 71#define DHT_DEFAULT_FIND_PEER_OPTIONS GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
64 72
65#define DHT_DEFAULT_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) 73#define DHT_DEFAULT_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1)
66 74
67/** 75/**
68 * Real maximum number of hops, at which point we refuse 76 * Real maximum number of hops, at which point we refuse
@@ -473,6 +481,11 @@ static unsigned int lowest_bucket; /* Initially equal to MAX_BUCKETS - 1 */
473static struct PeerBucket k_buckets[MAX_BUCKETS]; /* From 0 to MAX_BUCKETS - 1 */ 481static struct PeerBucket k_buckets[MAX_BUCKETS]; /* From 0 to MAX_BUCKETS - 1 */
474 482
475/** 483/**
484 * Hash map of all known peers, for easy removal from k_buckets on disconnect.
485 */
486static struct GNUNET_CONTAINER_MultiHashMap *all_known_peers;
487
488/**
476 * Maximum size for each bucket. 489 * Maximum size for each bucket.
477 */ 490 */
478static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; /* Initially equal to DEFAULT_BUCKET_SIZE */ 491static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; /* Initially equal to DEFAULT_BUCKET_SIZE */
@@ -798,6 +811,65 @@ static int find_current_bucket(const GNUNET_HashCode *hc)
798/** 811/**
799 * Find a routing table entry from a peer identity 812 * Find a routing table entry from a peer identity
800 * 813 *
814 * @param peer the peer to look up
815 *
816 * @return the bucket number holding the peer, GNUNET_SYSERR if not found
817 */
818static int
819find_bucket_by_peer(const struct PeerInfo *peer)
820{
821 int bucket;
822 struct PeerInfo *pos;
823
824 for (bucket = lowest_bucket; bucket < MAX_BUCKETS - 1; bucket++)
825 {
826 pos = k_buckets[bucket].head;
827 while (pos != NULL)
828 {
829 if (peer == pos)
830 return bucket;
831 pos = pos->next;
832 }
833 }
834
835 return GNUNET_SYSERR; /* No such peer. */
836}
837
838#if PRINT_TABLES
839/**
840 * Print the complete routing table for this peer.
841 */
842static void
843print_routing_table ()
844{
845 int bucket;
846 struct PeerInfo *pos;
847 char char_buf[30000];
848 int char_pos;
849 memset(char_buf, 0, sizeof(char_buf));
850 char_pos = 0;
851 char_pos += sprintf(&char_buf[char_pos], "Printing routing table for peer %s\n", my_short_id);
852 //fprintf(stderr, "Printing routing table for peer %s\n", my_short_id);
853 for (bucket = lowest_bucket; bucket < MAX_BUCKETS; bucket++)
854 {
855 pos = k_buckets[bucket].head;
856 char_pos += sprintf(&char_buf[char_pos], "Bucket %d:\n", bucket);
857 //fprintf(stderr, "Bucket %d:\n", bucket);
858 while (pos != NULL)
859 {
860 //fprintf(stderr, "\tPeer %s, best bucket %d, %d bits match\n", GNUNET_i2s(&pos->id), find_bucket(&pos->id.hashPubKey), matching_bits(&pos->id.hashPubKey, &my_identity.hashPubKey));
861 char_pos += sprintf(&char_buf[char_pos], "\tPeer %s, best bucket %d, %d bits match\n", GNUNET_i2s(&pos->id), find_bucket(&pos->id.hashPubKey), matching_bits(&pos->id.hashPubKey, &my_identity.hashPubKey));
862 pos = pos->next;
863 }
864 }
865 fprintf(stderr, "%s", char_buf);
866 fflush(stderr);
867}
868#endif
869
870/**
871 * Find a routing table entry from a peer identity
872 *
801 * @param peer the peer identity to look up 873 * @param peer the peer identity to look up
802 * 874 *
803 * @return the routing table entry, or NULL if not found 875 * @return the routing table entry, or NULL if not found
@@ -831,11 +903,14 @@ find_peer_by_id(const struct GNUNET_PeerIdentity *peer)
831 * the peer to 903 * the peer to
832 * @param latency the core reported latency of this peer 904 * @param latency the core reported latency of this peer
833 * @param distance the transport level distance to this peer 905 * @param distance the transport level distance to this peer
906 *
907 * @return the newly added PeerInfo
834 */ 908 */
835static void add_peer(const struct GNUNET_PeerIdentity *peer, 909static struct PeerInfo *
836 unsigned int bucket, 910add_peer(const struct GNUNET_PeerIdentity *peer,
837 struct GNUNET_TIME_Relative latency, 911 unsigned int bucket,
838 unsigned int distance) 912 struct GNUNET_TIME_Relative latency,
913 unsigned int distance)
839{ 914{
840 struct PeerInfo *new_peer; 915 struct PeerInfo *new_peer;
841 GNUNET_assert(bucket < MAX_BUCKETS); 916 GNUNET_assert(bucket < MAX_BUCKETS);
@@ -850,6 +925,8 @@ static void add_peer(const struct GNUNET_PeerIdentity *peer,
850 k_buckets[bucket].tail, 925 k_buckets[bucket].tail,
851 new_peer); 926 new_peer);
852 k_buckets[bucket].peers_size++; 927 k_buckets[bucket].peers_size++;
928
929 return new_peer;
853} 930}
854 931
855/** 932/**
@@ -870,6 +947,8 @@ static void remove_peer (struct PeerInfo *peer,
870 k_buckets[bucket].tail, 947 k_buckets[bucket].tail,
871 peer); 948 peer);
872 k_buckets[bucket].peers_size--; 949 k_buckets[bucket].peers_size--;
950 if ((bucket == lowest_bucket) && (k_buckets[lowest_bucket].peers_size == 0) && (lowest_bucket < MAX_BUCKETS - 1))
951 lowest_bucket++;
873} 952}
874 953
875/** 954/**
@@ -884,6 +963,21 @@ static void delete_peer (struct PeerInfo *peer,
884{ 963{
885 struct P2PPendingMessage *pos; 964 struct P2PPendingMessage *pos;
886 struct P2PPendingMessage *next; 965 struct P2PPendingMessage *next;
966 //fprintf(stderr, "BEFORE REMOVAL\n");
967 //print_routing_table();
968#if EXTRA_CHECKS
969 struct PeerInfo *peer_pos;
970
971 peer_pos = k_buckets[bucket].head;
972 while ((peer_pos != NULL) && (peer_pos != peer))
973 peer_pos = peer_pos->next;
974 if (peer_pos == NULL)
975 {
976 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s:%s: Expected peer `%s' in bucket %d\n", my_short_id, "DHT", GNUNET_i2s(&peer->id), bucket);
977 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s:%s: Lowest bucket: %d, find_current_bucket: %d, peer resides in bucket: %d\n", my_short_id, "DHT", lowest_bucket, find_current_bucket(&peer->id.hashPubKey), find_bucket_by_peer(peer));
978 }
979 GNUNET_assert(peer_pos != NULL);
980#endif
887 remove_peer(peer, bucket); /* First remove the peer from its bucket */ 981 remove_peer(peer, bucket); /* First remove the peer from its bucket */
888 982
889 if (peer->send_task != GNUNET_SCHEDULER_NO_TASK) 983 if (peer->send_task != GNUNET_SCHEDULER_NO_TASK)
@@ -898,9 +992,43 @@ static void delete_peer (struct PeerInfo *peer,
898 GNUNET_free(pos); 992 GNUNET_free(pos);
899 pos = next; 993 pos = next;
900 } 994 }
995
996 GNUNET_assert(GNUNET_CONTAINER_multihashmap_contains(all_known_peers, &peer->id.hashPubKey));
997 GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (all_known_peers, &peer->id.hashPubKey, peer));
901 GNUNET_free(peer); 998 GNUNET_free(peer);
999 //fprintf(stderr, "AFTER REMOVAL\n");
1000 //print_routing_table();
902} 1001}
903 1002
1003
1004/**
1005 * Iterator over hash map entries.
1006 *
1007 * @param cls closure
1008 * @param key current key code
1009 * @param value PeerInfo of the peer to move to new lowest bucket
1010 * @return GNUNET_YES if we should continue to
1011 * iterate,
1012 * GNUNET_NO if not.
1013 */
1014static int move_lowest_bucket (void *cls,
1015 const GNUNET_HashCode * key,
1016 void *value)
1017{
1018 struct PeerInfo *peer = value;
1019 int new_bucket;
1020
1021 new_bucket = lowest_bucket - 1;
1022 remove_peer(peer, lowest_bucket);
1023 GNUNET_CONTAINER_DLL_insert_after(k_buckets[new_bucket].head,
1024 k_buckets[new_bucket].tail,
1025 k_buckets[new_bucket].tail,
1026 peer);
1027 k_buckets[new_bucket].peers_size++;
1028 return GNUNET_YES;
1029}
1030
1031
904/** 1032/**
905 * The current lowest bucket is full, so change the lowest 1033 * The current lowest bucket is full, so change the lowest
906 * bucket to the next lower down, and move any appropriate 1034 * bucket to the next lower down, and move any appropriate
@@ -908,84 +1036,61 @@ static void delete_peer (struct PeerInfo *peer,
908 */ 1036 */
909static void enable_next_bucket() 1037static void enable_next_bucket()
910{ 1038{
911 unsigned int new_bucket; 1039 struct GNUNET_CONTAINER_MultiHashMap *to_remove;
912 unsigned int to_remove;
913 int i;
914 struct PeerInfo *to_remove_list[bucket_size]; /* We either use CPU by making a list, or memory with array. Use memory. */
915 struct PeerInfo *pos; 1040 struct PeerInfo *pos;
916 GNUNET_assert(lowest_bucket > 0); 1041 GNUNET_assert(lowest_bucket > 0);
917 1042 to_remove = GNUNET_CONTAINER_multihashmap_create(bucket_size);
918 pos = k_buckets[lowest_bucket].head; 1043 pos = k_buckets[lowest_bucket].head;
919 memset(to_remove_list, 0, sizeof(to_remove_list)); 1044
920 to_remove = 0; 1045#if PRINT_TABLES
1046 fprintf(stderr, "Printing RT before new bucket\n");
1047 print_routing_table();
1048#endif
921 /* Populate the array of peers which should be in the next lowest bucket */ 1049 /* Populate the array of peers which should be in the next lowest bucket */
922 while (pos->next != NULL) 1050 while (pos != NULL)
923 { 1051 {
924 if (find_bucket(&pos->id.hashPubKey) < lowest_bucket) 1052 if (find_bucket(&pos->id.hashPubKey) < lowest_bucket)
925 { 1053 GNUNET_CONTAINER_multihashmap_put(to_remove, &pos->id.hashPubKey, pos, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
926 to_remove_list[to_remove] = pos;
927 to_remove++;
928 }
929 pos = pos->next; 1054 pos = pos->next;
930 } 1055 }
931 new_bucket = lowest_bucket - 1;
932 1056
933 /* Remove peers from lowest bucket, insert into next lowest bucket */ 1057 /* Remove peers from lowest bucket, insert into next lowest bucket */
934 for (i = 0; i < bucket_size; i++) 1058 GNUNET_CONTAINER_multihashmap_iterate(to_remove, &move_lowest_bucket, NULL);
935 { 1059 lowest_bucket = lowest_bucket - 1;
936 if (to_remove_list[i] != NULL) 1060#if PRINT_TABLES
937 { 1061 fprintf(stderr, "Printing RT after new bucket\n");
938 remove_peer(to_remove_list[i], lowest_bucket); 1062 print_routing_table();
939 GNUNET_CONTAINER_DLL_insert_after(k_buckets[new_bucket].head, 1063#endif
940 k_buckets[new_bucket].tail,
941 k_buckets[new_bucket].tail,
942 to_remove_list[i]);
943 k_buckets[new_bucket].peers_size++;
944 }
945 else
946 break;
947 }
948 lowest_bucket = new_bucket;
949} 1064}
1065
1066
950/** 1067/**
951 * Attempt to add a peer to our k-buckets. 1068 * Attempt to add a peer to our k-buckets.
952 * 1069 *
953 * @param peer, the peer identity of the peer being added 1070 * @param peer, the peer identity of the peer being added
954 * 1071 *
955 * @return GNUNET_YES if the peer was added, 1072 * @return NULL if the peer was not added,
956 * GNUNET_NO if not, 1073 * pointer to PeerInfo for new peer otherwise
957 * GNUNET_SYSERR on err (peer is us!)
958 */ 1074 */
959static int try_add_peer(const struct GNUNET_PeerIdentity *peer, 1075static struct PeerInfo *
960 unsigned int bucket, 1076try_add_peer(const struct GNUNET_PeerIdentity *peer,
961 struct GNUNET_TIME_Relative latency, 1077 unsigned int bucket,
962 unsigned int distance) 1078 struct GNUNET_TIME_Relative latency,
1079 unsigned int distance)
963{ 1080{
964 int peer_bucket; 1081 int peer_bucket;
965 1082 struct PeerInfo *new_peer;
966 peer_bucket = find_current_bucket(&peer->hashPubKey); 1083 peer_bucket = find_current_bucket(&peer->hashPubKey);
967 if (peer_bucket == GNUNET_SYSERR) 1084 if (peer_bucket == GNUNET_SYSERR)
968 return GNUNET_SYSERR; 1085 return NULL;
969 1086
970 GNUNET_assert(peer_bucket >= lowest_bucket); 1087 GNUNET_assert(peer_bucket >= lowest_bucket);
971 if ((k_buckets[peer_bucket].peers_size) < bucket_size) 1088 new_peer = add_peer(peer, peer_bucket, latency, distance);
972 { 1089
973 add_peer(peer, peer_bucket, latency, distance); 1090 if ((k_buckets[lowest_bucket].peers_size) >= bucket_size)
974 return GNUNET_YES; 1091 enable_next_bucket();
975 } 1092
976 else if ((peer_bucket == lowest_bucket) && (lowest_bucket > 0)) 1093 return new_peer;
977 {
978 enable_next_bucket();
979 return try_add_peer(peer, bucket, latency, distance); /* Recurse, if proper bucket still full ping peers */
980 }
981 else if ((k_buckets[peer_bucket].peers_size) == bucket_size)
982 {
983 /* TODO: implement ping_oldest_peer */
984 //ping_oldest_peer(bucket, peer, latency, distance); /* Find oldest peer, ping it. If no response, remove and add new peer! */
985 return GNUNET_NO;
986 }
987 GNUNET_break(0);
988 return GNUNET_NO;
989} 1094}
990 1095
991 1096
@@ -1181,9 +1286,10 @@ static int route_result_message(void *cls,
1181 { 1286 {
1182 if (GNUNET_YES == consider_peer(&new_peer)) 1287 if (GNUNET_YES == consider_peer(&new_peer))
1183 { 1288 {
1184 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s:%s Received HELLO message for another peer, offering to transport!\n", my_short_id, "DHT");
1185 GNUNET_TRANSPORT_offer_hello(transport_handle, hello_msg); 1289 GNUNET_TRANSPORT_offer_hello(transport_handle, hello_msg);
1186 GNUNET_CORE_peer_request_connect(sched, cfg, GNUNET_TIME_UNIT_FOREVER_REL, &new_peer, NULL, NULL); /* FIXME: Do we need this??? */ 1290 /* GNUNET_CORE_peer_request_connect(sched, cfg, GNUNET_TIME_UNIT_FOREVER_REL, &new_peer, NULL, NULL); */
1291 /* peer_request_connect call causes service to segfault */
1292 /* FIXME: Do we need this (peer_request_connect call)??? */
1187 } 1293 }
1188 } 1294 }
1189 1295
@@ -1440,7 +1546,7 @@ handle_dht_find_peer (void *cls,
1440 ntohs (find_msg->size), 1546 ntohs (find_msg->size),
1441 sizeof (struct GNUNET_MessageHeader)); 1547 sizeof (struct GNUNET_MessageHeader));
1442#endif 1548#endif
1443 if ((my_hello == NULL) || (message_context->closest != GNUNET_YES)) 1549 if (my_hello == NULL)
1444 { 1550 {
1445#if DEBUG_DHT 1551#if DEBUG_DHT
1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1474,6 +1580,14 @@ handle_dht_find_peer (void *cls,
1474 new_msg_ctx->bloom = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K); 1580 new_msg_ctx->bloom = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
1475 new_msg_ctx->hop_count = 0; 1581 new_msg_ctx->hop_count = 0;
1476 route_result_message(cls, find_peer_result, new_msg_ctx); 1582 route_result_message(cls, find_peer_result, new_msg_ctx);
1583#if DEBUG_DHT_ROUTING
1584 if ((debug_routes) && (dhtlog_handle != NULL))
1585 {
1586 dhtlog_handle->insert_query (NULL, message_context->unique_id, DHTLOG_FIND_PEER,
1587 message_context->hop_count, GNUNET_YES, &my_identity,
1588 message_context->key);
1589 }
1590#endif
1477 //send_reply_to_client(message_context->client, find_peer_result, message_context->unique_id); 1591 //send_reply_to_client(message_context->client, find_peer_result, message_context->unique_id);
1478 GNUNET_free(find_peer_result); 1592 GNUNET_free(find_peer_result);
1479} 1593}
@@ -1613,6 +1727,7 @@ find_closest_peer (const GNUNET_HashCode *hc)
1613 unsigned int lowest_distance; 1727 unsigned int lowest_distance;
1614 unsigned int temp_distance; 1728 unsigned int temp_distance;
1615 int bucket; 1729 int bucket;
1730 int count;
1616 1731
1617 lowest_distance = -1; 1732 lowest_distance = -1;
1618 1733
@@ -1623,7 +1738,8 @@ find_closest_peer (const GNUNET_HashCode *hc)
1623 for (bucket = lowest_bucket; bucket < MAX_BUCKETS; bucket++) 1738 for (bucket = lowest_bucket; bucket < MAX_BUCKETS; bucket++)
1624 { 1739 {
1625 pos = k_buckets[bucket].head; 1740 pos = k_buckets[bucket].head;
1626 while (pos != NULL) 1741 count = 0;
1742 while ((pos != NULL) && (count < bucket_size))
1627 { 1743 {
1628 temp_distance = distance(&pos->id.hashPubKey, hc); 1744 temp_distance = distance(&pos->id.hashPubKey, hc);
1629 if (temp_distance <= lowest_distance) 1745 if (temp_distance <= lowest_distance)
@@ -1632,6 +1748,7 @@ find_closest_peer (const GNUNET_HashCode *hc)
1632 current_closest = pos; 1748 current_closest = pos;
1633 } 1749 }
1634 pos = pos->next; 1750 pos = pos->next;
1751 count++;
1635 } 1752 }
1636 } 1753 }
1637 GNUNET_assert(current_closest != NULL); 1754 GNUNET_assert(current_closest != NULL);
@@ -1652,6 +1769,7 @@ am_closest_peer (const GNUNET_HashCode * target)
1652 int bits; 1769 int bits;
1653 int other_bits; 1770 int other_bits;
1654 int bucket_num; 1771 int bucket_num;
1772 int count;
1655 struct PeerInfo *pos; 1773 struct PeerInfo *pos;
1656 unsigned int my_distance; 1774 unsigned int my_distance;
1657 1775
@@ -1663,13 +1781,15 @@ am_closest_peer (const GNUNET_HashCode * target)
1663 my_distance = distance(&my_identity.hashPubKey, target); 1781 my_distance = distance(&my_identity.hashPubKey, target);
1664 1782
1665 pos = k_buckets[bucket_num].head; 1783 pos = k_buckets[bucket_num].head;
1666 while (pos != NULL) 1784 count = 0;
1785 while ((pos != NULL) && (count < bucket_size))
1667 { 1786 {
1668 other_bits = matching_bits(&pos->id.hashPubKey, target); 1787 other_bits = matching_bits(&pos->id.hashPubKey, target);
1669 if (other_bits > bits) 1788 if (other_bits > bits)
1670 return GNUNET_NO; 1789 return GNUNET_NO;
1671 else if (other_bits == bits) /* We match the same number of bits, do distance comparison */ 1790 else if (other_bits == bits) /* We match the same number of bits, do distance comparison */
1672 { 1791 {
1792 /* FIXME: why not just return GNUNET_YES here? We are certainly close. */
1673 if (distance(&pos->id.hashPubKey, target) < my_distance) 1793 if (distance(&pos->id.hashPubKey, target) < my_distance)
1674 return GNUNET_NO; 1794 return GNUNET_NO;
1675 } 1795 }
@@ -1724,6 +1844,7 @@ select_peer (const GNUNET_HashCode * target,
1724{ 1844{
1725 unsigned int distance; 1845 unsigned int distance;
1726 unsigned int bc; 1846 unsigned int bc;
1847 unsigned int count;
1727 struct PeerInfo *pos; 1848 struct PeerInfo *pos;
1728#if USE_KADEMLIA 1849#if USE_KADEMLIA
1729 const struct PeerInfo *chosen; 1850 const struct PeerInfo *chosen;
@@ -1769,7 +1890,8 @@ select_peer (const GNUNET_HashCode * target,
1769 for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) 1890 for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++)
1770 { 1891 {
1771 pos = k_buckets[bc].head; 1892 pos = k_buckets[bc].head;
1772 while (pos != NULL) 1893 count = 0;
1894 while ((pos != NULL) && (count < bucket_size))
1773 { 1895 {
1774 if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) 1896 if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
1775 total_distance += (unsigned long long)inverse_distance (target, &pos->id.hashPubKey); 1897 total_distance += (unsigned long long)inverse_distance (target, &pos->id.hashPubKey);
@@ -1779,6 +1901,7 @@ select_peer (const GNUNET_HashCode * target,
1779 my_short_id, "DHT", total_distance, GNUNET_i2s(&pos->id), GNUNET_h2s(target) , inverse_distance(target, &pos->id.hashPubKey)); 1901 my_short_id, "DHT", total_distance, GNUNET_i2s(&pos->id), GNUNET_h2s(target) , inverse_distance(target, &pos->id.hashPubKey));
1780#endif 1902#endif
1781 pos = pos->next; 1903 pos = pos->next;
1904 count++;
1782 } 1905 }
1783 } 1906 }
1784 if (total_distance == 0) 1907 if (total_distance == 0)
@@ -1790,7 +1913,8 @@ select_peer (const GNUNET_HashCode * target,
1790 for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) 1913 for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++)
1791 { 1914 {
1792 pos = k_buckets[bc].head; 1915 pos = k_buckets[bc].head;
1793 while (pos != NULL) 1916 count = 0;
1917 while ((pos != NULL) && (count < bucket_size))
1794 { 1918 {
1795 if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) 1919 if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
1796 { 1920 {
@@ -1808,6 +1932,7 @@ select_peer (const GNUNET_HashCode * target,
1808#endif 1932#endif
1809 } 1933 }
1810 pos = pos->next; 1934 pos = pos->next;
1935 count++;
1811 } 1936 }
1812 } 1937 }
1813#if DEBUG_DHT 1938#if DEBUG_DHT
@@ -2023,7 +2148,7 @@ static int route_message(void *cls,
2023 if ((handle_dht_get (cls, msg, message_context) > 0) && (stop_on_found == GNUNET_YES)) 2148 if ((handle_dht_get (cls, msg, message_context) > 0) && (stop_on_found == GNUNET_YES))
2024 forward_count = 0; 2149 forward_count = 0;
2025 break; 2150 break;
2026 case GNUNET_MESSAGE_TYPE_DHT_PUT: /* Check if closest, if so insert data. FIXME: thresholding?*/ 2151 case GNUNET_MESSAGE_TYPE_DHT_PUT: /* Check if closest, if so insert data. FIXME: thresholding to reduce complexity?*/
2027 if (message_context->closest == GNUNET_YES) 2152 if (message_context->closest == GNUNET_YES)
2028 { 2153 {
2029#if DEBUG_DHT_ROUTING 2154#if DEBUG_DHT_ROUTING
@@ -2050,12 +2175,24 @@ static int route_message(void *cls,
2050#endif 2175#endif
2051 break; 2176 break;
2052 case GNUNET_MESSAGE_TYPE_DHT_FIND_PEER: /* Check if closest and not started by us, check options, add to requests seen */ 2177 case GNUNET_MESSAGE_TYPE_DHT_FIND_PEER: /* Check if closest and not started by us, check options, add to requests seen */
2053 if (0 != memcmp(message_context->peer, &my_identity, sizeof(struct GNUNET_PeerIdentity))) 2178 if (((message_context->hop_count > 0) && (0 != memcmp(message_context->peer, &my_identity, sizeof(struct GNUNET_PeerIdentity)))) || (message_context->client != NULL))
2054 { 2179 {
2055 cache_response (cls, message_context); 2180 cache_response (cls, message_context);
2056 if ((message_context->closest == GNUNET_YES) || (message_context->msg_options == GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) 2181 if ((message_context->closest == GNUNET_YES) || (message_context->msg_options == GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE))
2057 handle_dht_find_peer (cls, msg, message_context); 2182 handle_dht_find_peer (cls, msg, message_context);
2058 } 2183 }
2184#if DEBUG_DHT_ROUTING
2185 if (message_context->hop_count == 0) /* Locally initiated request */
2186 {
2187 if ((debug_routes) && (dhtlog_handle != NULL))
2188 {
2189 dhtlog_handle->insert_dhtkey(NULL, message_context->key);
2190 dhtlog_handle->insert_query (NULL, message_context->unique_id, DHTLOG_FIND_PEER,
2191 message_context->hop_count, GNUNET_NO, &my_identity,
2192 message_context->key);
2193 }
2194 }
2195#endif
2059 break; 2196 break;
2060 default: 2197 default:
2061 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2198 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -2065,7 +2202,7 @@ static int route_message(void *cls,
2065 for (i = 0; i < forward_count; i++) 2202 for (i = 0; i < forward_count; i++)
2066 { 2203 {
2067 selected = select_peer(message_context->key, message_context->bloom); 2204 selected = select_peer(message_context->key, message_context->bloom);
2068 2205 /* FIXME: either log to sql or log to stats or both when selected is NULL at this point! */
2069 if (selected != NULL) 2206 if (selected != NULL)
2070 { 2207 {
2071 GNUNET_CONTAINER_bloomfilter_add(message_context->bloom, &selected->id.hashPubKey); 2208 GNUNET_CONTAINER_bloomfilter_add(message_context->bloom, &selected->id.hashPubKey);
@@ -2160,7 +2297,7 @@ send_find_peer_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
2160 find_peer_msg->type = htons(GNUNET_MESSAGE_TYPE_DHT_FIND_PEER); 2297 find_peer_msg->type = htons(GNUNET_MESSAGE_TYPE_DHT_FIND_PEER);
2161 memset(&message_context, 0, sizeof(struct DHT_MessageContext)); 2298 memset(&message_context, 0, sizeof(struct DHT_MessageContext));
2162 message_context.key = &my_identity.hashPubKey; 2299 message_context.key = &my_identity.hashPubKey;
2163 message_context.unique_id = GNUNET_ntohll (GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK, (uint64_t)-1)); 2300 message_context.unique_id = GNUNET_ntohll (GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_STRONG, (uint64_t)-1));
2164 message_context.replication = ntohl (DHT_DEFAULT_FIND_PEER_REPLICATION); 2301 message_context.replication = ntohl (DHT_DEFAULT_FIND_PEER_REPLICATION);
2165 message_context.msg_options = ntohl (DHT_DEFAULT_FIND_PEER_OPTIONS); 2302 message_context.msg_options = ntohl (DHT_DEFAULT_FIND_PEER_OPTIONS);
2166 message_context.network_size = estimate_diameter(); 2303 message_context.network_size = estimate_diameter();
@@ -2488,7 +2625,7 @@ void handle_core_connect (void *cls,
2488 struct GNUNET_TIME_Relative latency, 2625 struct GNUNET_TIME_Relative latency,
2489 uint32_t distance) 2626 uint32_t distance)
2490{ 2627{
2491 int ret; 2628 struct PeerInfo *ret;
2492 2629
2493#if DEBUG_DHT 2630#if DEBUG_DHT
2494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2631 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2500,13 +2637,37 @@ void handle_core_connect (void *cls,
2500 find_current_bucket(&peer->hashPubKey), 2637 find_current_bucket(&peer->hashPubKey),
2501 latency, 2638 latency,
2502 distance); 2639 distance);
2640 if (ret != NULL)
2641 GNUNET_CONTAINER_multihashmap_put(all_known_peers, &peer->hashPubKey, ret, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2503#if DEBUG_DHT 2642#if DEBUG_DHT
2504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2505 "%s:%s Adding peer to routing list: %s\n", my_short_id, "DHT", ret == GNUNET_YES ? "PEER ADDED" : "NOT ADDED"); 2644 "%s:%s Adding peer to routing list: %s\n", my_short_id, "DHT", ret == NULL ? "NOT ADDED" : "PEER ADDED");
2506#endif 2645#endif
2507} 2646}
2508 2647
2509/** 2648/**
2649 * Method called whenever a peer disconnects.
2650 *
2651 * @param cls closure
2652 * @param peer peer identity this notification is about
2653 */
2654void handle_core_disconnect (void *cls,
2655 const struct
2656 GNUNET_PeerIdentity * peer)
2657{
2658 struct PeerInfo *to_remove;
2659 int current_bucket;
2660
2661 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s:%s: Received peer disconnect message for peer `%s' from %s\n", my_short_id, "DHT", GNUNET_i2s(peer), "CORE");
2662
2663 GNUNET_assert(GNUNET_CONTAINER_multihashmap_contains(all_known_peers, &peer->hashPubKey));
2664 to_remove = GNUNET_CONTAINER_multihashmap_get(all_known_peers, &peer->hashPubKey);
2665 GNUNET_assert(0 == memcmp(peer, &to_remove->id, sizeof(struct GNUNET_PeerIdentity)));
2666 current_bucket = find_current_bucket(&to_remove->id.hashPubKey);
2667 delete_peer(to_remove, current_bucket);
2668}
2669
2670/**
2510 * Process dht requests. 2671 * Process dht requests.
2511 * 2672 *
2512 * @param cls closure 2673 * @param cls closure
@@ -2529,8 +2690,8 @@ run (void *cls,
2529 GNUNET_TIME_UNIT_FOREVER_REL, 2690 GNUNET_TIME_UNIT_FOREVER_REL,
2530 NULL, /* Closure passed to DHT functionas around? */ 2691 NULL, /* Closure passed to DHT functionas around? */
2531 &core_init, /* Call core_init once connected */ 2692 &core_init, /* Call core_init once connected */
2532 &handle_core_connect, /* Don't care about connects */ 2693 &handle_core_connect, /* Handle connects */
2533 NULL, /* FIXME: remove peers on disconnects */ 2694 &handle_core_disconnect, /* FIXME: remove peers on disconnects */
2534 NULL, /* Do we care about "status" updates? */ 2695 NULL, /* Do we care about "status" updates? */
2535 NULL, /* Don't want notified about all incoming messages */ 2696 NULL, /* Don't want notified about all incoming messages */
2536 GNUNET_NO, /* For header only inbound notification */ 2697 GNUNET_NO, /* For header only inbound notification */
@@ -2550,8 +2711,8 @@ run (void *cls,
2550 lowest_bucket = MAX_BUCKETS - 1; 2711 lowest_bucket = MAX_BUCKETS - 1;
2551 forward_list.hashmap = GNUNET_CONTAINER_multihashmap_create(MAX_OUTSTANDING_FORWARDS / 10); 2712 forward_list.hashmap = GNUNET_CONTAINER_multihashmap_create(MAX_OUTSTANDING_FORWARDS / 10);
2552 forward_list.minHeap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN); 2713 forward_list.minHeap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
2553 /* Scheduled the task to clean up when shutdown is called */ 2714 all_known_peers = GNUNET_CONTAINER_multihashmap_create(MAX_BUCKETS / 8);
2554 2715 GNUNET_assert(all_known_peers != NULL);
2555 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(cfg, "dht_testing", "mysql_logging")) 2716 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(cfg, "dht_testing", "mysql_logging"))
2556 { 2717 {
2557 debug_routes = GNUNET_YES; 2718 debug_routes = GNUNET_YES;
@@ -2589,10 +2750,13 @@ run (void *cls,
2589 } 2750 }
2590 } 2751 }
2591 2752
2753#if DO_FIND_PEER
2592 GNUNET_SCHEDULER_add_delayed (sched, 2754 GNUNET_SCHEDULER_add_delayed (sched,
2593 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30), 2755 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30),
2594 &send_find_peer_message, NULL); 2756 &send_find_peer_message, NULL);
2757#endif
2595 2758
2759 /* Scheduled the task to clean up when shutdown is called */
2596 cleanup_task = GNUNET_SCHEDULER_add_delayed (sched, 2760 cleanup_task = GNUNET_SCHEDULER_add_delayed (sched,
2597 GNUNET_TIME_UNIT_FOREVER_REL, 2761 GNUNET_TIME_UNIT_FOREVER_REL,
2598 &shutdown_task, NULL); 2762 &shutdown_task, NULL);