diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-08-11 15:48:56 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-08-11 15:48:56 +0000 |
commit | 5c51bf63fa7cca2d96c6b2f9318b3fd805ac3628 (patch) | |
tree | 0f29aebffd76cdcfbd5678b8156e248abe2876ba /src/dht/gnunet-service-dht.c | |
parent | 1b0834b9cb28cc6dfa3984ace3bfcb5d5f57e84f (diff) | |
download | gnunet-5c51bf63fa7cca2d96c6b2f9318b3fd805ac3628.tar.gz gnunet-5c51bf63fa7cca2d96c6b2f9318b3fd805ac3628.zip |
fix for kademlia routing
Diffstat (limited to 'src/dht/gnunet-service-dht.c')
-rw-r--r-- | src/dht/gnunet-service-dht.c | 243 |
1 files changed, 152 insertions, 91 deletions
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c index fd9694fee..9c301183b 100644 --- a/src/dht/gnunet-service-dht.c +++ b/src/dht/gnunet-service-dht.c | |||
@@ -69,9 +69,12 @@ | |||
69 | 69 | ||
70 | #define DHT_DEFAULT_FIND_PEER_REPLICATION 10 | 70 | #define DHT_DEFAULT_FIND_PEER_REPLICATION 10 |
71 | 71 | ||
72 | #define DHT_MAX_RECENT 100 | ||
73 | |||
72 | #define DHT_DEFAULT_FIND_PEER_OPTIONS GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | 74 | #define DHT_DEFAULT_FIND_PEER_OPTIONS GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE |
73 | 75 | ||
74 | #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1) | 76 | #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1) |
77 | |||
75 | #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | 78 | #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) |
76 | 79 | ||
77 | /** | 80 | /** |
@@ -351,7 +354,6 @@ struct DHT_MessageContext | |||
351 | */ | 354 | */ |
352 | struct DHTRouteSource | 355 | struct DHTRouteSource |
353 | { | 356 | { |
354 | |||
355 | /** | 357 | /** |
356 | * This is a DLL. | 358 | * This is a DLL. |
357 | */ | 359 | */ |
@@ -439,6 +441,35 @@ struct DHTResults | |||
439 | }; | 441 | }; |
440 | 442 | ||
441 | /** | 443 | /** |
444 | * DHT structure for recent requests. | ||
445 | */ | ||
446 | struct RecentRequests | ||
447 | { | ||
448 | /* | ||
449 | * Min heap for removal upon reaching limit | ||
450 | */ | ||
451 | struct GNUNET_CONTAINER_Heap *minHeap; | ||
452 | |||
453 | /* | ||
454 | * Hashmap for key based lookup | ||
455 | */ | ||
456 | struct GNUNET_CONTAINER_MultiHashMap *hashmap; | ||
457 | }; | ||
458 | |||
459 | struct RecentRequest | ||
460 | { | ||
461 | GNUNET_HashCode key; | ||
462 | uint64_t uid; | ||
463 | }; | ||
464 | |||
465 | |||
466 | #if 0 | ||
467 | /** | ||
468 | * Recent requests by hash/uid and by time inserted. | ||
469 | */ | ||
470 | static struct RecentRequests recent; | ||
471 | #endif | ||
472 | /** | ||
442 | * Don't use our routing algorithm, always route | 473 | * Don't use our routing algorithm, always route |
443 | * to closest peer; initially send requests to 3 | 474 | * to closest peer; initially send requests to 3 |
444 | * peers. | 475 | * peers. |
@@ -2086,99 +2117,101 @@ select_peer (const GNUNET_HashCode * target, | |||
2086 | unsigned long long total_distance; | 2117 | unsigned long long total_distance; |
2087 | unsigned long long selected; | 2118 | unsigned long long selected; |
2088 | 2119 | ||
2089 | if (strict_kademlia == GNUNET_YES) | 2120 | if (strict_kademlia == GNUNET_YES) |
2090 | { | 2121 | { |
2091 | largest_distance = 0; | 2122 | largest_distance = 0; |
2092 | chosen = NULL; | 2123 | chosen = NULL; |
2093 | for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) | 2124 | for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) |
2094 | { | 2125 | { |
2095 | pos = k_buckets[bc].head; | 2126 | pos = k_buckets[bc].head; |
2096 | count = 0; | 2127 | count = 0; |
2097 | while ((pos != NULL) && (count < bucket_size)) | 2128 | while ((pos != NULL) && (count < bucket_size)) |
2098 | { | 2129 | { |
2099 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) | 2130 | /* If we are doing strict Kademlia like routing, then checking the bloomfilter is basically cheating! */ |
2100 | { | ||
2101 | distance = inverse_distance (target, &pos->id.hashPubKey); | ||
2102 | if (distance > largest_distance) | ||
2103 | { | ||
2104 | chosen = pos; | ||
2105 | largest_distance = distance; | ||
2106 | } | ||
2107 | } | ||
2108 | count++; | ||
2109 | pos = pos->next; | ||
2110 | } | ||
2111 | } | ||
2112 | 2131 | ||
2113 | if ((largest_distance > 0) && (chosen != NULL)) | 2132 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) |
2114 | { | 2133 | { |
2115 | GNUNET_CONTAINER_bloomfilter_add(bloom, &chosen->id.hashPubKey); | 2134 | distance = inverse_distance (target, &pos->id.hashPubKey); |
2116 | return chosen; | 2135 | if (distance > largest_distance) |
2117 | } | 2136 | { |
2118 | else | 2137 | chosen = pos; |
2119 | { | 2138 | largest_distance = distance; |
2120 | return NULL; | 2139 | } |
2121 | } | 2140 | } |
2122 | } | 2141 | count++; |
2142 | pos = pos->next; | ||
2143 | } | ||
2144 | } | ||
2145 | |||
2146 | if ((largest_distance > 0) && (chosen != NULL)) | ||
2147 | { | ||
2148 | GNUNET_CONTAINER_bloomfilter_add(bloom, &chosen->id.hashPubKey); | ||
2149 | return chosen; | ||
2150 | } | ||
2151 | else | ||
2152 | { | ||
2153 | return NULL; | ||
2154 | } | ||
2155 | } | ||
2123 | else | 2156 | else |
2124 | { | 2157 | { |
2125 | /* GNUnet-style */ | 2158 | /* GNUnet-style */ |
2126 | total_distance = 0; | 2159 | total_distance = 0; |
2127 | for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) | 2160 | for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) |
2128 | { | 2161 | { |
2129 | pos = k_buckets[bc].head; | 2162 | pos = k_buckets[bc].head; |
2130 | count = 0; | 2163 | count = 0; |
2131 | while ((pos != NULL) && (count < bucket_size)) | 2164 | while ((pos != NULL) && (count < bucket_size)) |
2132 | { | 2165 | { |
2133 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) | 2166 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) |
2134 | total_distance += (unsigned long long)inverse_distance (target, &pos->id.hashPubKey); | 2167 | total_distance += (unsigned long long)inverse_distance (target, &pos->id.hashPubKey); |
2135 | #if DEBUG_DHT > 1 | 2168 | #if DEBUG_DHT > 1 |
2136 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2137 | "`%s:%s': Total distance is %llu, distance from %s to %s is %u\n", | 2170 | "`%s:%s': Total distance is %llu, distance from %s to %s is %u\n", |
2138 | my_short_id, "DHT", total_distance, GNUNET_i2s(&pos->id), GNUNET_h2s(target) , inverse_distance(target, &pos->id.hashPubKey)); | 2171 | my_short_id, "DHT", total_distance, GNUNET_i2s(&pos->id), GNUNET_h2s(target) , inverse_distance(target, &pos->id.hashPubKey)); |
2139 | #endif | 2172 | #endif |
2140 | pos = pos->next; | 2173 | pos = pos->next; |
2141 | count++; | 2174 | count++; |
2142 | } | 2175 | } |
2143 | } | 2176 | } |
2144 | if (total_distance == 0) | 2177 | if (total_distance == 0) |
2145 | { | 2178 | { |
2146 | return NULL; | 2179 | return NULL; |
2147 | } | 2180 | } |
2148 | 2181 | ||
2149 | selected = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, total_distance); | 2182 | selected = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, total_distance); |
2150 | for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) | 2183 | for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++) |
2151 | { | 2184 | { |
2152 | pos = k_buckets[bc].head; | 2185 | pos = k_buckets[bc].head; |
2153 | count = 0; | 2186 | count = 0; |
2154 | while ((pos != NULL) && (count < bucket_size)) | 2187 | while ((pos != NULL) && (count < bucket_size)) |
2155 | { | 2188 | { |
2156 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) | 2189 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) |
2157 | { | 2190 | { |
2158 | distance = inverse_distance (target, &pos->id.hashPubKey); | 2191 | distance = inverse_distance (target, &pos->id.hashPubKey); |
2159 | if (distance > selected) | 2192 | if (distance > selected) |
2160 | return pos; | 2193 | return pos; |
2161 | selected -= distance; | 2194 | selected -= distance; |
2162 | } | 2195 | } |
2163 | else | 2196 | else |
2164 | { | 2197 | { |
2165 | #if DEBUG_DHT | 2198 | #if DEBUG_DHT |
2166 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2167 | "`%s:%s': peer %s matches bloomfilter.\n", | 2200 | "`%s:%s': peer %s matches bloomfilter.\n", |
2168 | my_short_id, "DHT", GNUNET_i2s(&pos->id)); | 2201 | my_short_id, "DHT", GNUNET_i2s(&pos->id)); |
2169 | #endif | 2202 | #endif |
2170 | } | 2203 | } |
2171 | pos = pos->next; | 2204 | pos = pos->next; |
2172 | count++; | 2205 | count++; |
2173 | } | 2206 | } |
2174 | } | 2207 | } |
2175 | #if DEBUG_DHT | 2208 | #if DEBUG_DHT |
2176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2177 | "`%s:%s': peer %s matches bloomfilter.\n", | 2210 | "`%s:%s': peer %s matches bloomfilter.\n", |
2178 | my_short_id, "DHT", GNUNET_i2s(&pos->id)); | 2211 | my_short_id, "DHT", GNUNET_i2s(&pos->id)); |
2179 | #endif | 2212 | #endif |
2180 | return NULL; | 2213 | return NULL; |
2181 | } | 2214 | } |
2182 | } | 2215 | } |
2183 | 2216 | ||
2184 | 2217 | ||
@@ -2323,6 +2356,8 @@ static int route_message(void *cls, | |||
2323 | return 0; | 2356 | return 0; |
2324 | } | 2357 | } |
2325 | 2358 | ||
2359 | |||
2360 | |||
2326 | increment_stats(STAT_ROUTES); | 2361 | increment_stats(STAT_ROUTES); |
2327 | message_context->closest = am_closest_peer(message_context->key); | 2362 | message_context->closest = am_closest_peer(message_context->key); |
2328 | forward_count = get_forward_count(message_context->hop_count, message_context->replication); | 2363 | forward_count = get_forward_count(message_context->hop_count, message_context->replication); |
@@ -2387,7 +2422,33 @@ static int route_message(void *cls, | |||
2387 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 2422 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
2388 | "`%s': Message type (%d) not handled\n", "DHT", ntohs(msg->type)); | 2423 | "`%s': Message type (%d) not handled\n", "DHT", ntohs(msg->type)); |
2389 | } | 2424 | } |
2425 | #if 0 | ||
2426 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(recent->hashmap, message_context->key)) | ||
2427 | { | ||
2428 | if (GNUNET_SYSERR = GNUNET_CONTAINER_multihashmap_get_multiple (recent->hashmap, message_context->key, &find_matching_recent, &message_context)) /* Have too recently seen this request! */ | ||
2429 | { | ||
2430 | forward_count = 0; | ||
2431 | } | ||
2432 | else /* Exact match not found, but same key found */ | ||
2433 | { | ||
2434 | recent_req = GNUNET_CONTAINER_multihashmap_get(recent->hashmap, message_context->key); | ||
2435 | } | ||
2436 | } | ||
2437 | else | ||
2438 | { | ||
2439 | recent_req = GNUNET_malloc(sizeof(struct RecentRequest)); | ||
2440 | recent_req->uid = message_context->unique_id; | ||
2441 | memcmp(&recent_req->key, message_context->key, sizeof(GNUNET_HashCode)); | ||
2442 | recent_req->remove_task = GNUNET_SCHEDULER_add_delayed(sched, DEFAULT_RECENT_REMOVAL, &remove_recent, recent_req); | ||
2443 | GNUNET_CONTAINER_heap_insert(recent->minHeap, recent_req, GNUNET_TIME_absolute_get()); | ||
2444 | GNUNET_CONTAINER_multihashmap_put(recent->hashmap, message_context->key, recent_req, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
2445 | } | ||
2390 | 2446 | ||
2447 | if (GNUNET_CONTAINER_multihashmap_size(recent->hashmap) > DHT_MAX_RECENT) | ||
2448 | { | ||
2449 | remove_oldest_recent(); | ||
2450 | } | ||
2451 | #endif | ||
2391 | for (i = 0; i < forward_count; i++) | 2452 | for (i = 0; i < forward_count; i++) |
2392 | { | 2453 | { |
2393 | selected = select_peer(message_context->key, message_context->bloom); | 2454 | selected = select_peer(message_context->key, message_context->bloom); |