aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSupriti Singh <supritisingh08@gmail.com>2014-01-21 14:44:16 +0000
committerSupriti Singh <supritisingh08@gmail.com>2014-01-21 14:44:16 +0000
commitc9c39aeeac95bccfc6582c9ed028670f8e51fd21 (patch)
treeaf9d5c15a7e9cdb411f2d570c6b643b787f9629b
parentab88c7e4ab224f1ce3040104e813a28b7910e1ca (diff)
downloadgnunet-c9c39aeeac95bccfc6582c9ed028670f8e51fd21.tar.gz
gnunet-c9c39aeeac95bccfc6582c9ed028670f8e51fd21.zip
incomplete code for finger and friend tables
-rw-r--r--configure.ac2
-rwxr-xr-xcontrib/pogen.sh4
-rw-r--r--src/dht/dht_api.c4
-rw-r--r--src/dht/gnunet-dht-get.c3
-rw-r--r--src/dht/gnunet-dht-put.c1
-rw-r--r--src/dht/gnunet-service-dht.c1
-rw-r--r--src/dht/gnunet-service-dht_clients.c3
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c2
-rw-r--r--src/dht/gnunet-service-xdht.c4
-rw-r--r--src/dht/gnunet-service-xdht_clients.c6
-rw-r--r--src/dht/gnunet-service-xdht_neighbours.c2089
-rw-r--r--src/dht/gnunet-service-xdht_neighbours.h90
-rw-r--r--src/dht/gnunet-service-xdht_routing.c419
-rw-r--r--src/dht/gnunet-service-xdht_routing.h28
-rw-r--r--src/dht/test_dht_api.c1
-rw-r--r--src/include/gnunet_common.h2
-rw-r--r--src/include/gnunet_protocols.h9
-rw-r--r--src/statistics/test_statistics_api_data.conf1
18 files changed, 559 insertions, 2110 deletions
diff --git a/configure.ac b/configure.ac
index 8f0289106..36da278ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -323,7 +323,7 @@ AC_RUN_IFELSE(
323 if (!gcry_check_version (GCRYPT_VERSION)) 323 if (!gcry_check_version (GCRYPT_VERSION))
324 { 324 {
325 fprintf (stderr, "Version mismatch %s <-> %s \n", gcry_check_version (NULL), GCRYPT_VERSION); 325 fprintf (stderr, "Version mismatch %s <-> %s \n", gcry_check_version (NULL), GCRYPT_VERSION);
326 return 1; 326 return 1;
327 } 327 }
328 328
329 gcry_control (GCRYCTL_DISABLE_SECMEM, 0); 329 gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
diff --git a/contrib/pogen.sh b/contrib/pogen.sh
index 288e19244..c8c091116 100755
--- a/contrib/pogen.sh
+++ b/contrib/pogen.sh
@@ -1,3 +1,3 @@
1#!/bin/sh 1#!/bin/sh
2find src -name "*.c" | grep -v \# | grep -v /test_ | grep -v /perf_ | grep -v _old | grep -v chat | sort > po/POTFILES.in 2find src -name "*.c" | grep -v \# | grep -v /test_ | grep -v /perf_ | grep -v _old | grep -v chat | sort > /po/POTFILES.in
3grep -l _\( `find src -name "*.h"` | grep -v "platform.h" | grep -v _old | grep -v chat | sort >> po/POTFILES.in 3grep -l _\( `find src -name "*.h"` | grep -v "platform.h" | grep -v _old | grep -v chat | sort >> /po/POTFILES.in
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index e045a8b75..f94d1f67a 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -599,6 +599,7 @@ transmit_pending (void *cls,
599 struct PendingMessage *head; 599 struct PendingMessage *head;
600 size_t tsize; 600 size_t tsize;
601 601
602
602 handle->th = NULL; 603 handle->th = NULL;
603 if (NULL == buf) 604 if (NULL == buf)
604 { 605 {
@@ -635,6 +636,7 @@ transmit_pending (void *cls,
635 { 636 {
636 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting to process replies from DHT\n"); 637 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting to process replies from DHT\n");
637 handle->in_receive = GNUNET_YES; 638 handle->in_receive = GNUNET_YES;
639
638 GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle, 640 GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle,
639 GNUNET_TIME_UNIT_FOREVER_REL); 641 GNUNET_TIME_UNIT_FOREVER_REL);
640 } 642 }
@@ -900,6 +902,7 @@ service_message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
900 uint16_t msize; 902 uint16_t msize;
901 int ret; 903 int ret;
902 904
905
903 if (NULL == msg) 906 if (NULL == msg)
904 { 907 {
905 LOG (GNUNET_ERROR_TYPE_DEBUG, 908 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -1148,6 +1151,7 @@ GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
1148 struct PendingMessage *pending; 1151 struct PendingMessage *pending;
1149 struct GNUNET_DHT_PutHandle *ph; 1152 struct GNUNET_DHT_PutHandle *ph;
1150 1153
1154
1151 msize = sizeof (struct GNUNET_DHT_ClientPutMessage) + size; 1155 msize = sizeof (struct GNUNET_DHT_ClientPutMessage) + size;
1152 if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || 1156 if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1153 (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) 1157 (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE))
diff --git a/src/dht/gnunet-dht-get.c b/src/dht/gnunet-dht-get.c
index e7e809323..2483e3cd1 100644
--- a/src/dht/gnunet-dht-get.c
+++ b/src/dht/gnunet-dht-get.c
@@ -26,6 +26,7 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_dht_service.h" 27#include "gnunet_dht_service.h"
28 28
29#define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__)
29/** 30/**
30 * The type of the query 31 * The type of the query
31 */ 32 */
@@ -150,6 +151,8 @@ run (void *cls, char *const *args, const char *cfgfile,
150{ 151{
151 struct GNUNET_HashCode key; 152 struct GNUNET_HashCode key;
152 153
154
155
153 cfg = c; 156 cfg = c;
154 if (NULL == query_key) 157 if (NULL == query_key)
155 { 158 {
diff --git a/src/dht/gnunet-dht-put.c b/src/dht/gnunet-dht-put.c
index 67884c423..008f989a1 100644
--- a/src/dht/gnunet-dht-put.c
+++ b/src/dht/gnunet-dht-put.c
@@ -229,6 +229,7 @@ main (int argc, char *const *argv)
229 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 229 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
230 return 2; 230 return 2;
231 231
232
232 return (GNUNET_OK == 233 return (GNUNET_OK ==
233 GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-put", 234 GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-put",
234 gettext_noop 235 gettext_noop
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index 5efa9ddc6..cc1e0dc6b 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -145,6 +145,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
145 const struct GNUNET_CONFIGURATION_Handle *c) 145 const struct GNUNET_CONFIGURATION_Handle *c)
146{ 146{
147 GDS_cfg = c; 147 GDS_cfg = c;
148
148 if (GNUNET_OK != 149 if (GNUNET_OK !=
149 GNUNET_CONFIGURATION_get_value_time (c, "transport", "HELLO_EXPIRATION", &hello_expiration)) 150 GNUNET_CONFIGURATION_get_value_time (c, "transport", "HELLO_EXPIRATION", &hello_expiration))
150 { 151 {
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index c6e72cf44..5195fa3ec 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -1023,7 +1023,7 @@ forward_reply (void *cls, const struct GNUNET_HashCode * key, void *value)
1023 int do_free; 1023 int do_free;
1024 struct GNUNET_HashCode ch; 1024 struct GNUNET_HashCode ch;
1025 unsigned int i; 1025 unsigned int i;
1026 1026
1027 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 1027 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
1028 "XDHT CLIENT-RESULT %s\n", 1028 "XDHT CLIENT-RESULT %s\n",
1029 GNUNET_h2s (key)); 1029 GNUNET_h2s (key));
@@ -1198,6 +1198,7 @@ GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
1198 frc.type = type; 1198 frc.type = type;
1199 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply, 1199 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply,
1200 &frc); 1200 &frc);
1201
1201 if (GNUNET_NO == frc.do_copy) 1202 if (GNUNET_NO == frc.do_copy)
1202 { 1203 {
1203 /* did not match any of the requests, free! */ 1204 /* did not match any of the requests, free! */
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index d89f26685..d15af4ee6 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -2224,4 +2224,4 @@ GDS_NEIGHBOURS_get_id ()
2224} 2224}
2225 2225
2226 2226
2227/* end of gnunet-service-dht_neighbours.c */ 2227/* end of gnunet-service-dht_neighbours.c */ \ No newline at end of file
diff --git a/src/dht/gnunet-service-xdht.c b/src/dht/gnunet-service-xdht.c
index a421d25b3..432fea354 100644
--- a/src/dht/gnunet-service-xdht.c
+++ b/src/dht/gnunet-service-xdht.c
@@ -24,6 +24,7 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * @author Nathan Evans 25 * @author Nathan Evans
26 */ 26 */
27
27#include "platform.h" 28#include "platform.h"
28#include "gnunet_block_lib.h" 29#include "gnunet_block_lib.h"
29#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
@@ -113,6 +114,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
113 GNUNET_TRANSPORT_disconnect (GDS_transport_handle); 114 GNUNET_TRANSPORT_disconnect (GDS_transport_handle);
114 GDS_transport_handle = NULL; 115 GDS_transport_handle = NULL;
115 } 116 }
117
116 GDS_NEIGHBOURS_done (); 118 GDS_NEIGHBOURS_done ();
117 GDS_DATACACHE_done (); 119 GDS_DATACACHE_done ();
118 GDS_ROUTING_done (); 120 GDS_ROUTING_done ();
@@ -152,11 +154,13 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
152 } 154 }
153 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg); 155 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
154 GDS_stats = GNUNET_STATISTICS_create ("dht", GDS_cfg); 156 GDS_stats = GNUNET_STATISTICS_create ("dht", GDS_cfg);
157
155 GDS_ROUTING_init (); 158 GDS_ROUTING_init ();
156 GDS_NSE_init (); 159 GDS_NSE_init ();
157 GDS_DATACACHE_init (); 160 GDS_DATACACHE_init ();
158 GDS_HELLO_init (); 161 GDS_HELLO_init ();
159 GDS_CLIENTS_init (server); 162 GDS_CLIENTS_init (server);
163
160 if (GNUNET_OK != GDS_NEIGHBOURS_init ()) 164 if (GNUNET_OK != GDS_NEIGHBOURS_init ())
161 { 165 {
162 shutdown_task (NULL, NULL); 166 shutdown_task (NULL, NULL);
diff --git a/src/dht/gnunet-service-xdht_clients.c b/src/dht/gnunet-service-xdht_clients.c
index 9cc156e3d..72d086606 100644
--- a/src/dht/gnunet-service-xdht_clients.c
+++ b/src/dht/gnunet-service-xdht_clients.c
@@ -21,8 +21,7 @@
21/** 21/**
22 * @file dht/gnunet-service-xdht_clients.c 22 * @file dht/gnunet-service-xdht_clients.c
23 * @brief GNUnet DHT service's client management code 23 * @brief GNUnet DHT service's client management code
24 * @author Christian Grothoff 24 * @author Supriti Singh
25 * @author Nathan Evans
26 */ 25 */
27 26
28#include "platform.h" 27#include "platform.h"
@@ -362,6 +361,7 @@ static void
362handle_client_disconnect (void *cls, 361handle_client_disconnect (void *cls,
363 struct GNUNET_SERVER_Client *client) 362 struct GNUNET_SERVER_Client *client)
364{ 363{
364
365 struct ClientList *pos; 365 struct ClientList *pos;
366 struct PendingMessage *reply; 366 struct PendingMessage *reply;
367 struct ClientMonitorRecord *monitor; 367 struct ClientMonitorRecord *monitor;
@@ -428,6 +428,7 @@ transmit_request (struct ClientQueryRecord *cqr)
428 LOG (GNUNET_ERROR_TYPE_DEBUG, 428 LOG (GNUNET_ERROR_TYPE_DEBUG,
429 "Initiating GET for %s, replication %u, already have %u replies\n", 429 "Initiating GET for %s, replication %u, already have %u replies\n",
430 GNUNET_h2s(&cqr->key), cqr->replication, cqr->seen_replies_count); 430 GNUNET_h2s(&cqr->key), cqr->replication, cqr->seen_replies_count);
431
431 GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication, 432 GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication,
432 0 /* hop count */ , 433 0 /* hop count */ ,
433 &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf, 434 &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf,
@@ -532,6 +533,7 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client,
532 peer_bf = 533 peer_bf =
533 GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, 534 GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE,
534 GNUNET_CONSTANTS_BLOOMFILTER_K); 535 GNUNET_CONSTANTS_BLOOMFILTER_K);
536
535 GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type), ntohl (dht_msg->options), 537 GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type), ntohl (dht_msg->options),
536 ntohl (dht_msg->desired_replication_level), 538 ntohl (dht_msg->desired_replication_level),
537 GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 539 GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c
index 8f47feef5..06891bb21 100644
--- a/src/dht/gnunet-service-xdht_neighbours.c
+++ b/src/dht/gnunet-service-xdht_neighbours.c
@@ -21,8 +21,7 @@
21/** 21/**
22 * @file dht/gnunet-service-xdht_neighbours.c 22 * @file dht/gnunet-service-xdht_neighbours.c
23 * @brief GNUnet DHT service's bucket and neighbour management code 23 * @brief GNUnet DHT service's bucket and neighbour management code
24 * @author Christian Grothoff 24 * @author Supriti Singh
25 * @author Nathan Evans
26 */ 25 */
27 26
28#include "platform.h" 27#include "platform.h"
@@ -49,27 +48,8 @@
49#include <fenv.h> 48#include <fenv.h>
50#include "dht.h" 49#include "dht.h"
51 50
52#define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__) 51/* The maximum possible fingers of a peer. */
53 52#define MAX_FINGERS 256
54/**
55 * How many buckets will we allow total.
56 */
57#define MAX_BUCKETS sizeof (struct GNUNET_HashCode) * 8
58
59/**
60 * What is the maximum number of peers in a given bucket.
61 */
62#define DEFAULT_BUCKET_SIZE 8
63
64/**
65 * Desired replication level for FIND PEER requests
66 */
67#define FIND_PEER_REPLICATION_LEVEL 4
68
69/**
70 * Maximum allowed replication level for all requests.
71 */
72#define MAXIMUM_REPLICATION_LEVEL 16
73 53
74/** 54/**
75 * Maximum allowed number of pending messages per peer. 55 * Maximum allowed number of pending messages per peer.
@@ -77,33 +57,24 @@
77#define MAXIMUM_PENDING_PER_PEER 64 57#define MAXIMUM_PENDING_PER_PEER 64
78 58
79/** 59/**
80 * How often to update our preference levels for peers in our routing tables. 60 * How long at least to wait before sending another find finger trail request.
81 */
82#define DHT_DEFAULT_PREFERENCE_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
83
84/**
85 * How long at least to wait before sending another find peer request.
86 */ 61 */
87#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) 62#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
88 63
89/** 64/**
90 * How long at most to wait before sending another find peer request. 65 * How long at most to wait before sending another find finger trail request.
91 */ 66 */
92#define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10) 67#define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
93 68
94/**
95 * How long at most to wait for transmission of a GET request to another peer?
96 */
97#define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
98
99/**
100 * Hello address expiration
101 */
102extern struct GNUNET_TIME_Relative hello_expiration;
103
104 69
105GNUNET_NETWORK_STRUCT_BEGIN 70GNUNET_NETWORK_STRUCT_BEGIN
106 71
72/* FIXME:
73 * 1) Bloomfilter is not required for X-Vine.
74 * Keep the field now but remove it when implementing PUT/GET.
75 * 2) also, check the field of put/get/result if all are required for
76 * x-vine or not. */
77
107/** 78/**
108 * P2P PUT message 79 * P2P PUT message
109 */ 80 */
@@ -255,175 +226,217 @@ struct PeerGetMessage
255 */ 226 */
256 struct GNUNET_HashCode key; 227 struct GNUNET_HashCode key;
257 228
258 /* xquery */
259
260 /* result bloomfilter */
261
262}; 229};
263GNUNET_NETWORK_STRUCT_END 230
264 231
265/** 232/**
266 * Linked list of messages to send to a particular other peer. 233 * FIXME : should change the fields
234 * P2P Trail setup message
267 */ 235 */
268struct P2PPendingMessage 236struct PeerTrailSetupMessage
269{ 237{
270 /** 238 /**
271 * Pointer to next item in the list 239 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
272 */
273 struct P2PPendingMessage *next;
274
275 /**
276 * Pointer to previous item in the list
277 */
278 struct P2PPendingMessage *prev;
279
280 /**
281 * Message importance level. FIXME: used? useful?
282 */
283 unsigned int importance;
284
285 /**
286 * When does this message time out?
287 */ 240 */
288 struct GNUNET_TIME_Absolute timeout; 241 struct GNUNET_MessageHeader header;
289 242
290 /** 243 /* Source peer which wants to find trail to one of its finger. */
291 * Actual message to be sent, allocated at the end of the struct: 244 struct GNUNET_PeerIdentity *source_peer;
292 * // msg = (cast) &pm[1]; 245
293 * // memcpy (&pm[1], data, len); 246 /* Finger id to which we want to set up the trail to. */
294 */ 247 struct GNUNET_PeerIdentity *destination_finger;
295 const struct GNUNET_MessageHeader *msg; 248
249 /* This field contains the peer to which this packet is forwarded.
250 If temp_destination = my_identity, then check if destination_finger = temp_destination.
251 If temp_destination != my_identity, then it means you are part of trail that
252 you take to temp_destination. So, search in routing table.
253 */
254 struct GNUNET_PeerIdentity *temp_destination;
255
256 /*FIXME: I want to store a list of all the peer_id which are part of trail in
257 this message
258 Also, when sending the reply back we are just going to read this list
259 backwards. Assuming that we add a new peer at the end of our list. */
260
261
296 262
297}; 263};
298
299
300/** 264/**
301 * Entry for a peer in a bucket. 265 * P2P Trail setup Result message
266 * TODO: Check the fields and if they are really required.
267 * FIXME: should change the fields
268 * it can contain the peertrailsetup only
269 * and we just read the list backwards and make the
270 * packet reach to destination
271 *There can be lots and lots of cases where the packet are lost but
272 * as we have non blocking function call we are ok
273 * i think i will implement and verify by printing the design.
302 */ 274 */
303struct PeerInfo 275struct PeerTrailSetupResultMessage
304{ 276{
305 /** 277 /**
306 * Next peer entry (DLL) 278 * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_RESULT_SETUP
307 */
308 struct PeerInfo *next;
309
310 /**
311 * Prev peer entry (DLL)
312 */ 279 */
313 struct PeerInfo *prev; 280 struct GNUNET_MessageHeader header;
314 281
315 /** 282 /**
316 * Count of outstanding messages for peer. 283 * Content type.
317 */ 284 */
318 unsigned int pending_count; 285 uint32_t type GNUNET_PACKED;
319 286
320 /** 287 /**
321 * Head of pending messages to be sent to this peer. 288 * Length of the PUT path that follows (if tracked).
322 */ 289 */
323 struct P2PPendingMessage *head; 290 uint32_t put_path_length GNUNET_PACKED;
324 291
325 /** 292 /**
326 * Tail of pending messages to be sent to this peer. 293 * Length of the GET path that follows (if tracked).
327 */ 294 */
328 struct P2PPendingMessage *tail; 295 uint32_t get_path_length GNUNET_PACKED;
329 296
330 /** 297 /**
331 * Core handle for sending messages to this peer. 298 * When does the content expire?
332 */ 299 */
333 struct GNUNET_CORE_TransmitHandle *th; 300 struct GNUNET_TIME_AbsoluteNBO expiration_time;
334 301
335 /** 302 /**
336 * Task for scheduling preference updates 303 * The key of the corresponding GET request.
337 */ 304 */
338 GNUNET_SCHEDULER_TaskIdentifier preference_task; 305 struct GNUNET_HashCode key;
339 306
340 /** 307 /* put path (if tracked) */
341 * What is the identity of the peer?
342 */
343 struct GNUNET_PeerIdentity id;
344 308
345#if 0 309 /* get path (if tracked) */
346 /**
347 * What is the average latency for replies received?
348 */
349 struct GNUNET_TIME_Relative latency;
350 310
351 /** 311 /* Payload */
352 * Transport level distance to peer.
353 */
354 unsigned int distance;
355#endif
356 312
357}; 313};
358 314
359 315GNUNET_NETWORK_STRUCT_END
316
317
360/** 318/**
361 * Peers are grouped into buckets. 319 * Linked list of messages to send to a particular other peer.
362 */ 320 */
363struct PeerBucket 321struct P2PPendingMessage
364{ 322{
365 /** 323 /**
366 * Head of DLL 324 * Pointer to next item in the list
367 */ 325 */
368 struct PeerInfo *head; 326 struct P2PPendingMessage *next;
369 327
370 /** 328 /**
371 * Tail of DLL 329 * Pointer to previous item in the list
372 */ 330 */
373 struct PeerInfo *tail; 331 struct P2PPendingMessage *prev;
374 332
375 /** 333 /**
376 * Number of peers in the bucket. 334 * When does this message time out?
377 */ 335 */
378 unsigned int peers_size; 336 struct GNUNET_TIME_Absolute timeout;
337
338 /**
339 * Message importance level. FIXME: used? useful?
340 */
341 unsigned int importance;
342
343 /**
344 * Actual message to be sent, allocated at the end of the struct:
345 * // msg = (cast) &pm[1];
346 * // memcpy (&pm[1], data, len);
347 */
348 const struct GNUNET_MessageHeader *msg;
349
379}; 350};
380 351
381 352
382/** 353/**
383 * Do we cache all results that we are routing in the local datacache? 354 * Entry in friend_peers map.
384 */ 355 */
385static int cache_results; 356struct FriendInfo
357{
358
359 /**
360 * What is the identity of the peer?
361 */
362 struct GNUNET_PeerIdentity id;
386 363
387/** 364 /**
388 * Should routing details be logged to stderr (for debugging)? 365 * Count of outstanding messages for peer.
389 */ 366 */
390static int log_route_details_stderr; 367 unsigned int pending_count;
391 368
392/** 369 /**
393 * The lowest currently used bucket, initially 0 (for 0-bits matching bucket). 370 * Head of pending messages to be sent to this peer.
394 */ 371 */
395static unsigned int closest_bucket; 372 struct P2PPendingMessage *head;
396 373
397/** 374 /**
398 * How many peers have we added since we sent out our last 375 * Tail of pending messages to be sent to this peer.
399 * find peer request? 376 */
400 */ 377 struct P2PPendingMessage *tail;
401static unsigned int newly_found_peers;
402 378
403/** 379
404 * Option for testing that disables the 'connect' function of the DHT. 380 /**
405 */ 381 * TODO - How and where to use this?
406static int disable_try_connect; 382 * Core handle for sending messages to this peer.
383 */
384 struct GNUNET_CORE_TransmitHandle *th;
407 385
408/** 386};
409 * The buckets. Array of size MAX_BUCKET_SIZE. Offset 0 means 0 bits matching.
410 */
411static struct PeerBucket k_buckets[MAX_BUCKETS];
412 387
413/** 388/**
414 * Hash map of all known peers, for easy removal from k_buckets on disconnect. 389 * Linked List of peers which are part of trail to reach a particular Finger.
415 */ 390 */
416static struct GNUNET_CONTAINER_MultiPeerMap *all_known_peers; 391struct TrailList
392{
393 /**
394 * Pointer to next item in the list
395 */
396 struct TrailList *next;
397
398 /**
399 * Pointer to previous item in the list
400 */
401 struct TrailList *prev;
402};
417 403
418/** 404/**
419 * Maximum size for each bucket. 405 * Entry in finger_peers map.
420 */ 406 */
421static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; 407struct FingerInfo
408{
409 /**
410 * What is the identity of the peer?
411 */
412 struct GNUNET_PeerIdentity id;
413
414 /* FIXME:: Range of keys for which this finger is responsible */
415 /* Start of the interval of keys for which this finger is responsible. */
416 unsigned int interval_start;
417
418 /* End of the interval of keys for which this finger is responsible. */
419 unsigned int interval_end;
420
421
422 /* FIXME:: A double link list which stores the trail to reach it from given peer .*/
423
424 /**
425 * Head of trail list.
426 */
427 struct TrailList *head;
428
429 /**
430 * Tail of trail list.
431 */
432 struct TrailList *tail;
433};
434
422 435
423/** 436/**
424 * Task that sends FIND PEER requests. 437 * Task that sends FIND FINGER TRAIL requests.
425 */ 438 */
426static GNUNET_SCHEDULER_TaskIdentifier find_peer_task; 439static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
427 440
428/** 441/**
429 * Identity of this peer. 442 * Identity of this peer.
@@ -436,340 +449,35 @@ static struct GNUNET_PeerIdentity my_identity;
436static struct GNUNET_HashCode my_identity_hash; 449static struct GNUNET_HashCode my_identity_hash;
437 450
438/** 451/**
439 * Handle to CORE. 452 * Hash map of all the friends of a peer
440 */
441static struct GNUNET_CORE_Handle *core_api;
442
443/**
444 * Handle to ATS.
445 */
446static struct GNUNET_ATS_PerformanceHandle *atsAPI;
447
448
449
450/**
451 * Find the optimal bucket for this key.
452 *
453 * @param hc the hashcode to compare our identity to
454 * @return the proper bucket index, or GNUNET_SYSERR
455 * on error (same hashcode)
456 */
457static int
458find_bucket (const struct GNUNET_HashCode *hc)
459{
460 unsigned int bits;
461
462 bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, hc);
463 if (bits == MAX_BUCKETS)
464 {
465 /* How can all bits match? Got my own ID? */
466 GNUNET_break (0);
467 return GNUNET_SYSERR;
468 }
469 return MAX_BUCKETS - bits - 1;
470}
471
472
473/**
474 * Let GNUnet core know that we like the given peer.
475 *
476 * @param cls the `struct PeerInfo` of the peer
477 * @param tc scheduler context.
478 */
479static void
480update_core_preference (void *cls,
481 const struct GNUNET_SCHEDULER_TaskContext *tc)
482{
483 struct PeerInfo *peer = cls;
484 uint64_t preference;
485 unsigned int matching;
486 int bucket;
487 struct GNUNET_HashCode phash;
488
489 peer->preference_task = GNUNET_SCHEDULER_NO_TASK;
490 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
491 return;
492 GNUNET_CRYPTO_hash (&peer->id,
493 sizeof (struct GNUNET_PeerIdentity),
494 &phash);
495 matching =
496 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
497 &phash);
498 if (matching >= 64)
499 matching = 63;
500 bucket = find_bucket (&phash);
501 if (bucket == GNUNET_SYSERR)
502 preference = 0;
503 else
504 {
505 GNUNET_assert (k_buckets[bucket].peers_size != 0);
506 preference = (1LL << matching) / k_buckets[bucket].peers_size;
507 }
508 if (preference == 0)
509 {
510 peer->preference_task =
511 GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL,
512 &update_core_preference, peer);
513 return;
514 }
515 GNUNET_STATISTICS_update (GDS_stats,
516 gettext_noop ("# Preference updates given to core"),
517 1, GNUNET_NO);
518 GNUNET_ATS_performance_change_preference (atsAPI, &peer->id,
519 GNUNET_ATS_PREFERENCE_BANDWIDTH,
520 (double) preference, GNUNET_ATS_PREFERENCE_END);
521 peer->preference_task =
522 GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL,
523 &update_core_preference, peer);
524
525
526}
527
528
529/**
530 * Closure for 'add_known_to_bloom'.
531 */ 453 */
532struct BloomConstructorContext 454static struct GNUNET_CONTAINER_MultiPeerMap *friend_peers;
533{
534 /**
535 * Bloom filter under construction.
536 */
537 struct GNUNET_CONTAINER_BloomFilter *bloom;
538
539 /**
540 * Mutator to use.
541 */
542 uint32_t bf_mutator;
543};
544
545 455
546/** 456/**
547 * Add each of the peers we already know to the bloom filter of 457 * Hash map of all the fingers of a peer
548 * the request so that we don't get duplicate HELLOs.
549 *
550 * @param cls the 'struct BloomConstructorContext'.
551 * @param key peer identity to add to the bloom filter
552 * @param value value the peer information (unused)
553 * @return #GNUNET_YES (we should continue to iterate)
554 */ 458 */
555static int 459static struct GNUNET_CONTAINER_MultiPeerMap *finger_peers;
556add_known_to_bloom (void *cls,
557 const struct GNUNET_PeerIdentity *key,
558 void *value)
559{
560 struct BloomConstructorContext *ctx = cls;
561 struct GNUNET_HashCode key_hash;
562 struct GNUNET_HashCode mh;
563
564 GNUNET_CRYPTO_hash (key, sizeof (struct GNUNET_PeerIdentity), &key_hash);
565 GNUNET_BLOCK_mingle_hash (&key_hash, ctx->bf_mutator, &mh);
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
567 "Adding known peer (%s) to bloomfilter for FIND PEER with mutation %u\n",
568 GNUNET_i2s (key), ctx->bf_mutator);
569 GNUNET_CONTAINER_bloomfilter_add (ctx->bloom, &mh);
570 return GNUNET_YES;
571}
572
573 460
574/** 461/**
575 * Task to send a find peer message for our own peer identifier 462 * Handle to ATS.
576 * so that we can find the closest peers in the network to ourselves
577 * and attempt to connect to them.
578 *
579 * @param cls closure for this task
580 * @param tc the context under which the task is running
581 */ 463 */
582static void 464static struct GNUNET_ATS_PerformanceHandle *atsAPI;
583send_find_peer_message (void *cls,
584 const struct GNUNET_SCHEDULER_TaskContext *tc)
585{
586 struct GNUNET_TIME_Relative next_send_time;
587 struct BloomConstructorContext bcc;
588 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
589
590 find_peer_task = GNUNET_SCHEDULER_NO_TASK;
591 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
592 return;
593 if (newly_found_peers > bucket_size)
594 {
595 /* If we are finding many peers already, no need to send out our request right now! */
596 find_peer_task =
597 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
598 &send_find_peer_message, NULL);
599 newly_found_peers = 0;
600 return;
601 }
602 bcc.bf_mutator =
603 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
604 bcc.bloom =
605 GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE,
606 GNUNET_CONSTANTS_BLOOMFILTER_K);
607 GNUNET_CONTAINER_multipeermap_iterate (all_known_peers, &add_known_to_bloom,
608 &bcc);
609 GNUNET_STATISTICS_update (GDS_stats,
610 gettext_noop ("# FIND PEER messages initiated"), 1,
611 GNUNET_NO);
612 peer_bf =
613 GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE,
614 GNUNET_CONSTANTS_BLOOMFILTER_K);
615 // FIXME: pass priority!?
616 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO,
617 GNUNET_DHT_RO_FIND_PEER,
618 FIND_PEER_REPLICATION_LEVEL, 0,
619 &my_identity_hash, NULL, 0, bcc.bloom,
620 bcc.bf_mutator, peer_bf);
621 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
622 GNUNET_CONTAINER_bloomfilter_free (bcc.bloom);
623 /* schedule next round */
624 next_send_time.rel_value_us =
625 DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us +
626 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
627 DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us /
628 (newly_found_peers + 1));
629 newly_found_peers = 0;
630 find_peer_task =
631 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_peer_message,
632 NULL);
633}
634
635 465
636/** 466/**
637 * Method called whenever a peer connects. 467 * Handle to CORE.
638 *
639 * @param cls closure
640 * @param peer peer identity this notification is about
641 */ 468 */
642static void 469static struct GNUNET_CORE_Handle *core_api;
643handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
644{
645 struct PeerInfo *ret;
646 struct GNUNET_HashCode phash;
647 int peer_bucket;
648
649 /* Check for connect to self message */
650 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
651 return;
652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
653 "Connected to %s\n",
654 GNUNET_i2s (peer));
655 if (GNUNET_YES ==
656 GNUNET_CONTAINER_multipeermap_contains (all_known_peers,
657 peer))
658 {
659 GNUNET_break (0);
660 return;
661 }
662 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
663 GNUNET_NO);
664 GNUNET_CRYPTO_hash (peer,
665 sizeof (struct GNUNET_PeerIdentity),
666 &phash);
667 peer_bucket = find_bucket (&phash);
668 GNUNET_assert ((peer_bucket >= 0) && (peer_bucket < MAX_BUCKETS));
669 ret = GNUNET_new (struct PeerInfo);
670#if 0
671 ret->latency = latency;
672 ret->distance = distance;
673#endif
674 ret->id = *peer;
675 GNUNET_CONTAINER_DLL_insert_tail (k_buckets[peer_bucket].head,
676 k_buckets[peer_bucket].tail, ret);
677 k_buckets[peer_bucket].peers_size++;
678 closest_bucket = GNUNET_MAX (closest_bucket, peer_bucket);
679 if ((peer_bucket > 0) && (k_buckets[peer_bucket].peers_size <= bucket_size))
680 {
681 ret->preference_task =
682 GNUNET_SCHEDULER_add_now (&update_core_preference, ret);
683 newly_found_peers++;
684 }
685 GNUNET_assert (GNUNET_OK ==
686 GNUNET_CONTAINER_multipeermap_put (all_known_peers,
687 peer, ret,
688 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
689 if (1 == GNUNET_CONTAINER_multipeermap_size (all_known_peers) &&
690 (GNUNET_YES != disable_try_connect))
691 {
692 /* got a first connection, good time to start with FIND PEER requests... */
693 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, NULL);
694 }
695}
696
697 470
698/** 471/**
699 * Method called whenever a peer disconnects. 472 * The highest finger_id that we have found trail to.
700 *
701 * @param cls closure
702 * @param peer peer identity this notification is about
703 */ 473 */
704static void 474static unsigned int finger_id;
705handle_core_disconnect (void *cls,
706 const struct GNUNET_PeerIdentity *peer)
707{
708 struct PeerInfo *to_remove;
709 int current_bucket;
710 struct P2PPendingMessage *pos;
711 unsigned int discarded;
712 struct GNUNET_HashCode phash;
713
714 /* Check for disconnect from self message */
715 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
716 return;
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718 "Disconnected %s\n",
719 GNUNET_i2s (peer));
720 to_remove =
721 GNUNET_CONTAINER_multipeermap_get (all_known_peers, peer);
722 if (NULL == to_remove)
723 {
724 GNUNET_break (0);
725 return;
726 }
727 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), -1,
728 GNUNET_NO);
729 GNUNET_assert (GNUNET_YES ==
730 GNUNET_CONTAINER_multipeermap_remove (all_known_peers,
731 peer,
732 to_remove));
733 if (GNUNET_SCHEDULER_NO_TASK != to_remove->preference_task)
734 {
735 GNUNET_SCHEDULER_cancel (to_remove->preference_task);
736 to_remove->preference_task = GNUNET_SCHEDULER_NO_TASK;
737 }
738 GNUNET_CRYPTO_hash (peer,
739 sizeof (struct GNUNET_PeerIdentity),
740 &phash);
741 current_bucket = find_bucket (&phash);
742 GNUNET_assert (current_bucket >= 0);
743 GNUNET_CONTAINER_DLL_remove (k_buckets[current_bucket].head,
744 k_buckets[current_bucket].tail, to_remove);
745 GNUNET_assert (k_buckets[current_bucket].peers_size > 0);
746 k_buckets[current_bucket].peers_size--;
747 while ((closest_bucket > 0) && (k_buckets[closest_bucket].peers_size == 0))
748 closest_bucket--;
749
750 if (to_remove->th != NULL)
751 {
752 GNUNET_CORE_notify_transmit_ready_cancel (to_remove->th);
753 to_remove->th = NULL;
754 }
755 discarded = 0;
756 while (NULL != (pos = to_remove->head))
757 {
758 GNUNET_CONTAINER_DLL_remove (to_remove->head, to_remove->tail, pos);
759 discarded++;
760 GNUNET_free (pos);
761 }
762 GNUNET_STATISTICS_update (GDS_stats,
763 gettext_noop
764 ("# Queued messages discarded (peer disconnected)"),
765 discarded, GNUNET_NO);
766 GNUNET_free (to_remove);
767}
768 475
769 476
770/** 477/**
771 * Called when core is ready to send a message we asked for 478 * Called when core is ready to send a message we asked for
772 * out to the destination. 479 * out to the destination. At the moment, I have just copied it from previous
480 * code.
773 * 481 *
774 * @param cls the 'struct PeerInfo' of the target peer 482 * @param cls the 'struct PeerInfo' of the target peer
775 * @param size number of bytes available in buf 483 * @param size number of bytes available in buf
@@ -779,7 +487,7 @@ handle_core_disconnect (void *cls,
779static size_t 487static size_t
780core_transmit_notify (void *cls, size_t size, void *buf) 488core_transmit_notify (void *cls, size_t size, void *buf)
781{ 489{
782 struct PeerInfo *peer = cls; 490 struct FriendInfo *peer = cls;
783 char *cbuf = buf; 491 char *cbuf = buf;
784 struct P2PPendingMessage *pending; 492 struct P2PPendingMessage *pending;
785 size_t off; 493 size_t off;
@@ -844,8 +552,9 @@ core_transmit_notify (void *cls, size_t size, void *buf)
844 * @param peer message queue to process 552 * @param peer message queue to process
845 */ 553 */
846static void 554static void
847process_peer_queue (struct PeerInfo *peer) 555process_peer_queue (struct FriendInfo *peer)
848{ 556{
557
849 struct P2PPendingMessage *pending; 558 struct P2PPendingMessage *pending;
850 559
851 if (NULL == (pending = peer->head)) 560 if (NULL == (pending = peer->head))
@@ -856,6 +565,8 @@ process_peer_queue (struct PeerInfo *peer)
856 gettext_noop 565 gettext_noop
857 ("# Bytes of bandwidth requested from core"), 566 ("# Bytes of bandwidth requested from core"),
858 ntohs (pending->msg->size), GNUNET_NO); 567 ntohs (pending->msg->size), GNUNET_NO);
568 /*FIXME : here I don't know the use of importance, time out
569 Will check at run time if its all correct. */
859 peer->th = 570 peer->th =
860 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, 571 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
861 pending->importance, 572 pending->importance,
@@ -868,377 +579,81 @@ process_peer_queue (struct PeerInfo *peer)
868 579
869 580
870/** 581/**
871 * To how many peers should we (on average) forward the request to 582 * This function is similar to get request but used specifically for trail
872 * obtain the desired target_replication count (on average). 583 * construction. I don't know if using GDS_NEIGHBOURS_handle_get is sufficient
873 * 584 * or we need this new function.
874 * @param hop_count number of hops the message has traversed 585 * @param Finger id to which we want to setup the trail.
875 * @param target_replication the number of total paths desired 586 * @param Friend id through which we will try to setup the trail.
876 * @return Some number of peers to forward the message to
877 */ 587 */
878static unsigned int 588void
879get_forward_count (uint32_t hop_count, uint32_t target_replication) 589GDS_NEIGHBOURS_trail_setup(struct GNUNET_PeerIdentity *finger_id,
880{ 590 struct FriendInfo *target_friend)
881 uint32_t random_value;
882 uint32_t forward_count;
883 float target_value;
884
885 if (hop_count > GDS_NSE_get () * 4.0)
886 {
887 /* forcefully terminate */
888 GNUNET_STATISTICS_update (GDS_stats,
889 gettext_noop ("# requests TTL-dropped"),
890 1, GNUNET_NO);
891 return 0;
892 }
893 if (hop_count > GDS_NSE_get () * 2.0)
894 {
895 /* Once we have reached our ideal number of hops, only forward to 1 peer */
896 return 1;
897 }
898 /* bound by system-wide maximum */
899 target_replication =
900 GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL, target_replication);
901 target_value =
902 1 + (target_replication - 1.0) / (GDS_NSE_get () +
903 ((float) (target_replication - 1.0) *
904 hop_count));
905 /* Set forward count to floor of target_value */
906 forward_count = (uint32_t) target_value;
907 /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
908 target_value = target_value - forward_count;
909 random_value =
910 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
911 if (random_value < (target_value * UINT32_MAX))
912 forward_count++;
913 return forward_count;
914}
915
916
917/**
918 * Compute the distance between have and target as a 32-bit value.
919 * Differences in the lower bits must count stronger than differences
920 * in the higher bits.
921 *
922 * @param target
923 * @param have
924 * @return 0 if have==target, otherwise a number
925 * that is larger as the distance between
926 * the two hash codes increases
927 */
928static unsigned int
929get_distance (const struct GNUNET_HashCode *target,
930 const struct GNUNET_HashCode *have)
931{
932 unsigned int bucket;
933 unsigned int msb;
934 unsigned int lsb;
935 unsigned int i;
936
937 /* We have to represent the distance between two 2^9 (=512)-bit
938 * numbers as a 2^5 (=32)-bit number with "0" being used for the
939 * two numbers being identical; furthermore, we need to
940 * guarantee that a difference in the number of matching
941 * bits is always represented in the result.
942 *
943 * We use 2^32/2^9 numerical values to distinguish between
944 * hash codes that have the same LSB bit distance and
945 * use the highest 2^9 bits of the result to signify the
946 * number of (mis)matching LSB bits; if we have 0 matching
947 * and hence 512 mismatching LSB bits we return -1 (since
948 * 512 itself cannot be represented with 9 bits) */
949
950 /* first, calculate the most significant 9 bits of our
951 * result, aka the number of LSBs */
952 bucket = GNUNET_CRYPTO_hash_matching_bits (target, have);
953 /* bucket is now a value between 0 and 512 */
954 if (bucket == 512)
955 return 0; /* perfect match */
956 if (bucket == 0)
957 return (unsigned int) -1; /* LSB differs; use max (if we did the bit-shifting
958 * below, we'd end up with max+1 (overflow)) */
959
960 /* calculate the most significant bits of the final result */
961 msb = (512 - bucket) << (32 - 9);
962 /* calculate the 32-9 least significant bits of the final result by
963 * looking at the differences in the 32-9 bits following the
964 * mismatching bit at 'bucket' */
965 lsb = 0;
966 for (i = bucket + 1;
967 (i < sizeof (struct GNUNET_HashCode) * 8) && (i < bucket + 1 + 32 - 9); i++)
968 {
969 if (GNUNET_CRYPTO_hash_get_bit (target, i) !=
970 GNUNET_CRYPTO_hash_get_bit (have, i))
971 lsb |= (1 << (bucket + 32 - 9 - i)); /* first bit set will be 10,
972 * last bit set will be 31 -- if
973 * i does not reach 512 first... */
974 }
975 return msb | lsb;
976}
977
978
979/**
980 * Check whether my identity is closer than any known peers. If a
981 * non-null bloomfilter is given, check if this is the closest peer
982 * that hasn't already been routed to.
983 *
984 * @param key hash code to check closeness to
985 * @param bloom bloomfilter, exclude these entries from the decision
986 * @return GNUNET_YES if node location is closest,
987 * GNUNET_NO otherwise.
988 */
989static int
990am_closest_peer (const struct GNUNET_HashCode *key,
991 const struct GNUNET_CONTAINER_BloomFilter *bloom)
992{
993 int bits;
994 int other_bits;
995 int bucket_num;
996 int count;
997 struct PeerInfo *pos;
998 struct GNUNET_HashCode phash;
999
1000 if (0 == memcmp (&my_identity_hash, key, sizeof (struct GNUNET_HashCode)))
1001 return GNUNET_YES;
1002 bucket_num = find_bucket (key);
1003 GNUNET_assert (bucket_num >= 0);
1004 bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, key);
1005 pos = k_buckets[bucket_num].head;
1006 count = 0;
1007 while ((pos != NULL) && (count < bucket_size))
1008 {
1009 GNUNET_CRYPTO_hash (&pos->id,
1010 sizeof (struct GNUNET_PeerIdentity),
1011 &phash);
1012 if ((bloom != NULL) &&
1013 (GNUNET_YES ==
1014 GNUNET_CONTAINER_bloomfilter_test (bloom, &phash)))
1015 {
1016 pos = pos->next;
1017 continue; /* Skip already checked entries */
1018 }
1019 other_bits = GNUNET_CRYPTO_hash_matching_bits (&phash, key);
1020 if (other_bits > bits)
1021 return GNUNET_NO;
1022 if (other_bits == bits) /* We match the same number of bits */
1023 return GNUNET_YES;
1024 pos = pos->next;
1025 }
1026 /* No peers closer, we are the closest! */
1027 return GNUNET_YES;
1028}
1029
1030
1031/**
1032 * Select a peer from the routing table that would be a good routing
1033 * destination for sending a message for "key". The resulting peer
1034 * must not be in the set of blocked peers.<p>
1035 *
1036 * Note that we should not ALWAYS select the closest peer to the
1037 * target, peers further away from the target should be chosen with
1038 * exponentially declining probability.
1039 *
1040 * FIXME: double-check that this is fine
1041 *
1042 *
1043 * @param key the key we are selecting a peer to route to
1044 * @param bloom a bloomfilter containing entries this request has seen already
1045 * @param hops how many hops has this message traversed thus far
1046 * @return Peer to route to, or NULL on error
1047 */
1048static struct PeerInfo *
1049select_peer (const struct GNUNET_HashCode * key,
1050 const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops)
1051{ 591{
1052 unsigned int bc; 592 /*
1053 unsigned int count; 593 1. first construct the trail message which should contain
1054 unsigned int selected; 594 * the source peer id, the finger peer id and randomly chosen one of our
1055 struct PeerInfo *pos; 595 * friends peer id. Should there be a new block type?
1056 unsigned int dist; 596 * Construct a message and add it to your peer queue of the friend you have
1057 unsigned int smallest_distance; 597 * chosen to send the packet to and then call process_peer_queue.
1058 struct PeerInfo *chosen; 598 * Just follow GDS_NEIGHBOURS_handle_reply to complete this function.
1059 struct GNUNET_HashCode phash; 599 */
1060 600 /*
1061 if (hops >= GDS_NSE_get ()) 601 * FIXME: check if pending message actually contains the correct data.
1062 { 602 */
1063 /* greedy selection (closest peer that is not in bloomfilter) */ 603 struct P2PPendingMessage *pending;
1064 smallest_distance = UINT_MAX; 604 /* FIXME: why I have defined as **? verify by testing. */
1065 chosen = NULL; 605 struct PeerTrailSetupMessage *tsm;
1066 for (bc = 0; bc <= closest_bucket; bc++) 606
1067 { 607
1068 pos = k_buckets[bc].head; 608 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_PEER)
1069 count = 0;
1070 while ((pos != NULL) && (count < bucket_size))
1071 {
1072 GNUNET_CRYPTO_hash (&pos->id,
1073 sizeof (struct GNUNET_PeerIdentity),
1074 &phash);
1075 if ((bloom == NULL) ||
1076 (GNUNET_NO ==
1077 GNUNET_CONTAINER_bloomfilter_test (bloom, &phash)))
1078 {
1079 dist = get_distance (key, &phash);
1080 if (dist < smallest_distance)
1081 {
1082 chosen = pos;
1083 smallest_distance = dist;
1084 }
1085 }
1086 else
1087 {
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089 "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1090 GNUNET_i2s (&pos->id), GNUNET_h2s (key));
1091 GNUNET_STATISTICS_update (GDS_stats,
1092 gettext_noop
1093 ("# Peers excluded from routing due to Bloomfilter"),
1094 1, GNUNET_NO);
1095 dist = get_distance (key, &phash);
1096 if (dist < smallest_distance)
1097 {
1098 chosen = NULL;
1099 smallest_distance = dist;
1100 }
1101 }
1102 count++;
1103 pos = pos->next;
1104 }
1105 }
1106 if (NULL == chosen)
1107 GNUNET_STATISTICS_update (GDS_stats,
1108 gettext_noop ("# Peer selection failed"), 1,
1109 GNUNET_NO);
1110 return chosen;
1111 }
1112
1113 /* select "random" peer */
1114 /* count number of peers that are available and not filtered */
1115 count = 0;
1116 for (bc = 0; bc <= closest_bucket; bc++)
1117 {
1118 pos = k_buckets[bc].head;
1119 while ((pos != NULL) && (count < bucket_size))
1120 { 609 {
1121 GNUNET_CRYPTO_hash (&pos->id, 610 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1122 sizeof (struct GNUNET_PeerIdentity), 611 1, GNUNET_NO);
1123 &phash);
1124 if ((bloom != NULL) &&
1125 (GNUNET_YES ==
1126 GNUNET_CONTAINER_bloomfilter_test (bloom, &phash)))
1127 {
1128 GNUNET_STATISTICS_update (GDS_stats,
1129 gettext_noop
1130 ("# Peers excluded from routing due to Bloomfilter"),
1131 1, GNUNET_NO);
1132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1133 "Excluded peer `%s' due to BF match in random routing for %s\n",
1134 GNUNET_i2s (&pos->id), GNUNET_h2s (key));
1135 pos = pos->next;
1136 continue; /* Ignore bloomfiltered peers */
1137 }
1138 count++;
1139 pos = pos->next;
1140 }
1141 }
1142 if (0 == count) /* No peers to select from! */
1143 {
1144 GNUNET_STATISTICS_update (GDS_stats,
1145 gettext_noop ("# Peer selection failed"), 1,
1146 GNUNET_NO);
1147 return NULL;
1148 }
1149 /* Now actually choose a peer */
1150 selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, count);
1151 count = 0;
1152 for (bc = 0; bc <= closest_bucket; bc++)
1153 {
1154 for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size)); pos = pos->next)
1155 {
1156 GNUNET_CRYPTO_hash (&pos->id,
1157 sizeof (struct GNUNET_PeerIdentity),
1158 &phash);
1159 if ((bloom != NULL) &&
1160 (GNUNET_YES ==
1161 GNUNET_CONTAINER_bloomfilter_test (bloom, &phash)))
1162 {
1163 continue; /* Ignore bloomfiltered peers */
1164 }
1165 if (0 == selected--)
1166 return pos;
1167 } 612 }
1168 } 613
1169 GNUNET_break (0); 614 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
1170 return NULL; 615 tsm = (struct PeerTrailSetupMessage *) &pending[1];
616 pending->msg = &tsm->header;
617 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
618 tsm->destination_finger = finger_id;
619 tsm->source_peer = &my_identity;
620 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
621 target_friend->pending_count++;
622 process_peer_queue(target_friend);
1171} 623}
1172 624
1173 625
1174/** 626/**FIXME: Old implementation just to remove error
1175 * Compute the set of peers that the given request should be 627 * Perform a GET operation. Forwards the given request to other
1176 * forwarded to. 628 * peers. Does not lookup the key locally. May do nothing if this is
629 * the only peer in the network (or if we are the closest peer in the
630 * network).
1177 * 631 *
1178 * @param key routing key 632 * @param type type of the block
1179 * @param bloom bloom filter excluding peers as targets, all selected 633 * @param options routing options
1180 * peers will be added to the bloom filter 634 * @param desired_replication_level desired replication count
1181 * @param hop_count number of hops the request has traversed so far 635 * @param hop_count how many hops did this request traverse so far?
1182 * @param target_replication desired number of replicas 636 * @param key key for the content
1183 * @param targets where to store an array of target peers (to be 637 * @param xquery extended query
1184 * free'd by the caller) 638 * @param xquery_size number of bytes in @a xquery
1185 * @return number of peers returned in 'targets'. 639 * @param reply_bf bloomfilter to filter duplicates
640 * @param reply_bf_mutator mutator for @a reply_bf
641 * @param peer_bf filter for peers not to select (again)
1186 */ 642 */
1187static unsigned int 643void
1188get_target_peers (const struct GNUNET_HashCode *key, 644GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1189 struct GNUNET_CONTAINER_BloomFilter *bloom, 645 enum GNUNET_DHT_RouteOption options,
1190 uint32_t hop_count, uint32_t target_replication, 646 uint32_t desired_replication_level,
1191 struct PeerInfo ***targets) 647 uint32_t hop_count, const struct GNUNET_HashCode * key,
648 const void *xquery, size_t xquery_size,
649 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
650 uint32_t reply_bf_mutator,
651 struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1192{ 652{
1193 unsigned int ret; 653
1194 unsigned int off;
1195 struct PeerInfo **rtargets;
1196 struct PeerInfo *nxt;
1197 struct GNUNET_HashCode nhash;
1198
1199 GNUNET_assert (NULL != bloom);
1200 ret = get_forward_count (hop_count, target_replication);
1201 if (0 == ret)
1202 {
1203 *targets = NULL;
1204 return 0;
1205 }
1206 rtargets = GNUNET_malloc (sizeof (struct PeerInfo *) * ret);
1207 for (off = 0; off < ret; off++)
1208 {
1209 nxt = select_peer (key, bloom, hop_count);
1210 if (NULL == nxt)
1211 break;
1212 rtargets[off] = nxt;
1213 GNUNET_CRYPTO_hash (&nxt->id,
1214 sizeof (struct GNUNET_PeerIdentity),
1215 &nhash);
1216 GNUNET_break (GNUNET_NO ==
1217 GNUNET_CONTAINER_bloomfilter_test (bloom,
1218 &nhash));
1219 GNUNET_CONTAINER_bloomfilter_add (bloom, &nhash);
1220 }
1221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1222 "Selected %u/%u peers at hop %u for %s (target was %u)\n", off,
1223 GNUNET_CONTAINER_multipeermap_size (all_known_peers),
1224 (unsigned int) hop_count, GNUNET_h2s (key), ret);
1225 if (0 == off)
1226 {
1227 GNUNET_free (rtargets);
1228 *targets = NULL;
1229 return 0;
1230 }
1231 *targets = rtargets;
1232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1233 "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1234 GNUNET_h2s (key),
1235 off,
1236 ret);
1237 return off;
1238} 654}
1239 655
1240 656/**FIXME: Old implementation just to remove error.
1241/**
1242 * Perform a PUT operation. Forwards the given request to other 657 * Perform a PUT operation. Forwards the given request to other
1243 * peers. Does not store the data locally. Does not give the 658 * peers. Does not store the data locally. Does not give the
1244 * data to local clients. May do nothing if this is the only 659 * data to local clients. May do nothing if this is the only
@@ -1269,307 +684,155 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1269 struct GNUNET_PeerIdentity *put_path, 684 struct GNUNET_PeerIdentity *put_path,
1270 const void *data, size_t data_size) 685 const void *data, size_t data_size)
1271{ 686{
1272 unsigned int target_count;
1273 unsigned int i;
1274 struct PeerInfo **targets;
1275 struct PeerInfo *target;
1276 struct P2PPendingMessage *pending;
1277 size_t msize;
1278 struct PeerPutMessage *ppm;
1279 struct GNUNET_PeerIdentity *pp;
1280 struct GNUNET_HashCode thash;
1281 687
1282 GNUNET_assert (NULL != bf); 688}
1283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 689/**
1284 "Adding myself (%s) to PUT bloomfilter for %s\n", 690 * Randomly choose one of your friends from the friends_peer map
1285 GNUNET_i2s (&my_identity), GNUNET_h2s (key)); 691 * @return Friend
1286 GNUNET_CONTAINER_bloomfilter_add (bf, &my_identity_hash); 692 */
1287 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT requests routed"), 693static struct FriendInfo *
1288 1, GNUNET_NO); 694get_friend()
1289 target_count = 695{
1290 get_target_peers (key, bf, hop_count, desired_replication_level, 696
1291 &targets); 697 return NULL;
1292 if (0 == target_count) 698}
1293 { 699
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 700/**
1295 "Routing PUT for %s terminates after %u hops at %s\n", 701 * Use Chord formula finger[i]=(n+2^(i-1))mod m,
1296 GNUNET_h2s (key), (unsigned int) hop_count, 702 * where i = current finger map index.
1297 GNUNET_i2s (&my_identity)); 703 * n = own peer identity
1298 return; 704 * m = number of bits in peer id.
1299 } 705 * @return finger_peer_id for which we have to find the trail through network.
1300 msize = 706 */
1301 put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + 707static struct GNUNET_PeerIdentity *
1302 sizeof (struct PeerPutMessage); 708finger_id_to_search()
1303 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 709{
1304 { 710 /* After finding the finger_id increment the value of 'i'
1305 put_path_length = 0; 711 so that the next search begins from there. */
1306 msize = data_size + sizeof (struct PeerPutMessage); 712 struct GNUNET_PeerIdentity *finger_peer_id;
1307 } 713
1308 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 714
1309 { 715
1310 GNUNET_break (0); 716 /* FIXME: This typecasting is not correct. */
1311 GNUNET_free (targets); 717 //finger_peer_id = ((unsigned int)(my_identity.public_key.q_y)+(2^(finger_id)))%MAX_FINGERS;
1312 return; 718
1313 } 719 /* Increment the next finger_id we should be searching. */
1314 GNUNET_STATISTICS_update (GDS_stats, 720 finger_id = (finger_id+1)%MAX_FINGERS;
1315 gettext_noop 721
1316 ("# PUT messages queued for transmission"), 722 return finger_peer_id;
1317 target_count, GNUNET_NO); 723
1318 for (i = 0; i < target_count; i++) 724}
725
726
727/**
728 * Task to send a find finger trail message. We attempt to find trail
729 * to our fingers in the network.
730 *
731 * @param cls closure for this task
732 * @param tc the context under which the task is running
733 */
734static void
735send_find_finger_trail_message (void *cls,
736 const struct GNUNET_SCHEDULER_TaskContext *tc)
737{
738 /* finger we are searching for */
739 struct GNUNET_PeerIdentity *finger_peer_id;
740 struct FriendInfo *friend_peer_id;
741 struct GNUNET_TIME_Relative next_send_time;
742
743 /* FIXME: Not sure if this is required. Here I am checking if I have
744 already found trail for each of the possible finger. If yes then don't look
745 anymore in the network. */
746 if (GNUNET_CONTAINER_multipeermap_size(finger_peers) == MAX_FINGERS)
1319 { 747 {
1320 target = targets[i]; 748 return;
1321 if (target->pending_count >= MAXIMUM_PENDING_PER_PEER)
1322 {
1323 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1324 1, GNUNET_NO);
1325 continue; /* skip */
1326 }
1327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1328 "Routing PUT for %s after %u hops to %s\n", GNUNET_h2s (key),
1329 (unsigned int) hop_count, GNUNET_i2s (&target->id));
1330 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1331 pending->importance = 0; /* FIXME */
1332 pending->timeout = expiration_time;
1333 ppm = (struct PeerPutMessage *) &pending[1];
1334 pending->msg = &ppm->header;
1335 ppm->header.size = htons (msize);
1336 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1337 ppm->options = htonl (options);
1338 ppm->type = htonl (type);
1339 ppm->hop_count = htonl (hop_count + 1);
1340 ppm->desired_replication_level = htonl (desired_replication_level);
1341 ppm->put_path_length = htonl (put_path_length);
1342 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1343 GNUNET_CRYPTO_hash (&target->id,
1344 sizeof (struct GNUNET_PeerIdentity),
1345 &thash);
1346 GNUNET_break (GNUNET_YES ==
1347 GNUNET_CONTAINER_bloomfilter_test (bf,
1348 &thash));
1349 GNUNET_assert (GNUNET_OK ==
1350 GNUNET_CONTAINER_bloomfilter_get_raw_data (bf,
1351 ppm->bloomfilter,
1352 DHT_BLOOM_SIZE));
1353 ppm->key = *key;
1354 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1355 memcpy (pp, put_path,
1356 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
1357 memcpy (&pp[put_path_length], data, data_size);
1358 GNUNET_CONTAINER_DLL_insert_tail (target->head, target->tail, pending);
1359 target->pending_count++;
1360 process_peer_queue (target);
1361 } 749 }
1362 GNUNET_free (targets); 750
751 /* Find the finger_peer_id to which we want to setup the trial */
752 finger_peer_id = finger_id_to_search();
753
754 /* Choose a friend randomly from your friend_peers map. */
755 friend_peer_id = get_friend();
756
757 GDS_NEIGHBOURS_trail_setup(finger_peer_id, friend_peer_id);
758
759 /* FIXME: Is using finger_id to generate random function ok here. */
760 next_send_time.rel_value_us =
761 DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us +
762 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
763 DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us /
764 (finger_id + 1));
765
766 find_finger_trail_task =
767 GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
768 NULL);
1363} 769}
1364 770
1365 771
1366/** 772/**
1367 * Perform a GET operation. Forwards the given request to other 773 * Method called whenever a peer connects.
1368 * peers. Does not lookup the key locally. May do nothing if this is
1369 * the only peer in the network (or if we are the closest peer in the
1370 * network).
1371 * 774 *
1372 * @param type type of the block 775 * @param cls closure
1373 * @param options routing options 776 * @param peer peer identity this notification is about
1374 * @param desired_replication_level desired replication count
1375 * @param hop_count how many hops did this request traverse so far?
1376 * @param key key for the content
1377 * @param xquery extended query
1378 * @param xquery_size number of bytes in @a xquery
1379 * @param reply_bf bloomfilter to filter duplicates
1380 * @param reply_bf_mutator mutator for @a reply_bf
1381 * @param peer_bf filter for peers not to select (again)
1382 */ 777 */
1383void 778static void
1384GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 779handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
1385 enum GNUNET_DHT_RouteOption options,
1386 uint32_t desired_replication_level,
1387 uint32_t hop_count, const struct GNUNET_HashCode * key,
1388 const void *xquery, size_t xquery_size,
1389 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
1390 uint32_t reply_bf_mutator,
1391 struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1392{ 780{
1393 unsigned int target_count; 781 /*When a peer is connected, then add it to your friend_peers map.
1394 unsigned int i; 782 Also, start an asynchronous method to look for your fingers that you can
1395 struct PeerInfo **targets; 783 reach whenever you get the first connection to the peer. Also try to
1396 struct PeerInfo *target; 784 reach to your predecessor. */
1397 struct P2PPendingMessage *pending; 785
1398 size_t msize; 786 struct FriendInfo *ret;
1399 struct PeerGetMessage *pgm; 787 struct GNUNET_HashCode phash;
1400 char *xq; 788
1401 size_t reply_bf_size; 789 /* Check for connect to self message */
1402 struct GNUNET_HashCode thash; 790 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
1403
1404 GNUNET_assert (NULL != peer_bf);
1405 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests routed"),
1406 1, GNUNET_NO);
1407 target_count =
1408 get_target_peers (key, peer_bf, hop_count, desired_replication_level,
1409 &targets);
1410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1411 "Adding myself (%s) to GET bloomfilter for %s\n",
1412 GNUNET_i2s (&my_identity), GNUNET_h2s (key));
1413 GNUNET_CONTAINER_bloomfilter_add (peer_bf, &my_identity_hash);
1414 if (0 == target_count)
1415 {
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417 "Routing GET for %s terminates after %u hops at %s\n",
1418 GNUNET_h2s (key), (unsigned int) hop_count,
1419 GNUNET_i2s (&my_identity));
1420 return; 791 return;
1421 } 792
1422 reply_bf_size = GNUNET_CONTAINER_bloomfilter_get_size (reply_bf); 793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1423 msize = xquery_size + sizeof (struct PeerGetMessage) + reply_bf_size; 794 "Connected to %s\n",
1424 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 795 GNUNET_i2s (peer));
796
797 if (GNUNET_YES ==
798 GNUNET_CONTAINER_multipeermap_contains (friend_peers,
799 peer))
1425 { 800 {
1426 GNUNET_break (0); 801 GNUNET_break (0);
1427 GNUNET_free (targets);
1428 return; 802 return;
1429 } 803 }
1430 GNUNET_STATISTICS_update (GDS_stats, 804
1431 gettext_noop 805 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
1432 ("# GET messages queued for transmission"), 806 GNUNET_NO);
1433 target_count, GNUNET_NO); 807 GNUNET_CRYPTO_hash (peer,
1434 /* forward request */ 808 sizeof (struct GNUNET_PeerIdentity),
1435 for (i = 0; i < target_count; i++) 809 &phash);
1436 { 810
1437 target = targets[i]; 811 ret = GNUNET_new (struct FriendInfo);
1438 if (target->pending_count >= MAXIMUM_PENDING_PER_PEER) 812 ret->id = *peer;
1439 { 813
1440 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 814 GNUNET_assert (GNUNET_OK ==
1441 1, GNUNET_NO); 815 GNUNET_CONTAINER_multipeermap_put (friend_peers,
1442 continue; /* skip */ 816 peer, ret,
1443 } 817 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 818
1445 "Routing GET for %s after %u hops to %s\n", GNUNET_h2s (key), 819 /* got a first connection, good time to start with FIND TRAIL TO FINGER requests... */
1446 (unsigned int) hop_count, GNUNET_i2s (&target->id)); 820 if (1 == GNUNET_CONTAINER_multipeermap_size(friend_peers))
1447 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); 821 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
1448 pending->importance = 0; /* FIXME */
1449 pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1450 pgm = (struct PeerGetMessage *) &pending[1];
1451 pending->msg = &pgm->header;
1452 pgm->header.size = htons (msize);
1453 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
1454 pgm->options = htonl (options);
1455 pgm->type = htonl (type);
1456 pgm->hop_count = htonl (hop_count + 1);
1457 pgm->desired_replication_level = htonl (desired_replication_level);
1458 pgm->xquery_size = htonl (xquery_size);
1459 pgm->bf_mutator = reply_bf_mutator;
1460 GNUNET_CRYPTO_hash (&target->id,
1461 sizeof (struct GNUNET_PeerIdentity),
1462 &thash);
1463 GNUNET_break (GNUNET_YES ==
1464 GNUNET_CONTAINER_bloomfilter_test (peer_bf,
1465 &thash));
1466 GNUNET_assert (GNUNET_OK ==
1467 GNUNET_CONTAINER_bloomfilter_get_raw_data (peer_bf,
1468 pgm->bloomfilter,
1469 DHT_BLOOM_SIZE));
1470 pgm->key = *key;
1471 xq = (char *) &pgm[1];
1472 memcpy (xq, xquery, xquery_size);
1473 if (NULL != reply_bf)
1474 GNUNET_assert (GNUNET_OK ==
1475 GNUNET_CONTAINER_bloomfilter_get_raw_data (reply_bf,
1476 &xq
1477 [xquery_size],
1478 reply_bf_size));
1479 GNUNET_CONTAINER_DLL_insert_tail (target->head, target->tail, pending);
1480 target->pending_count++;
1481 process_peer_queue (target);
1482 }
1483 GNUNET_free (targets);
1484} 822}
1485 823
1486 824
1487/** 825/**
1488 * Handle a reply (route to origin). Only forwards the reply back to 826 * Method called whenever a peer disconnects.
1489 * the given peer. Does not do local caching or forwarding to local
1490 * clients.
1491 * 827 *
1492 * @param target neighbour that should receive the block (if still connected) 828 * @param cls closure
1493 * @param type type of the block 829 * @param peer peer identity this notification is about
1494 * @param expiration_time when does the content expire
1495 * @param key key for the content
1496 * @param put_path_length number of entries in @a put_path
1497 * @param put_path peers the original PUT traversed (if tracked)
1498 * @param get_path_length number of entries in @a get_path
1499 * @param get_path peers this reply has traversed so far (if tracked)
1500 * @param data payload of the reply
1501 * @param data_size number of bytes in @a data
1502 */ 830 */
1503void 831static void
1504GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, 832handle_core_disconnect (void *cls,
1505 enum GNUNET_BLOCK_Type type, 833 const struct GNUNET_PeerIdentity *peer)
1506 struct GNUNET_TIME_Absolute expiration_time,
1507 const struct GNUNET_HashCode * key,
1508 unsigned int put_path_length,
1509 const struct GNUNET_PeerIdentity *put_path,
1510 unsigned int get_path_length,
1511 const struct GNUNET_PeerIdentity *get_path,
1512 const void *data, size_t data_size)
1513{ 834{
1514 struct PeerInfo *pi;
1515 struct P2PPendingMessage *pending;
1516 size_t msize;
1517 struct PeerResultMessage *prm;
1518 struct GNUNET_PeerIdentity *paths;
1519
1520 msize =
1521 data_size + sizeof (struct PeerResultMessage) + (get_path_length +
1522 put_path_length) *
1523 sizeof (struct GNUNET_PeerIdentity);
1524 if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1525 (get_path_length >
1526 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1527 (put_path_length >
1528 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1529 (data_size > GNUNET_SERVER_MAX_MESSAGE_SIZE))
1530 {
1531 GNUNET_break (0);
1532 return;
1533 }
1534 pi = GNUNET_CONTAINER_multipeermap_get (all_known_peers, target);
1535 if (NULL == pi)
1536 {
1537 /* peer disconnected in the meantime, drop reply */
1538 return;
1539 }
1540 if (pi->pending_count >= MAXIMUM_PENDING_PER_PEER)
1541 {
1542 /* skip */
1543 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1544 1, GNUNET_NO);
1545 return;
1546 }
1547 835
1548 GNUNET_STATISTICS_update (GDS_stats,
1549 gettext_noop
1550 ("# RESULT messages queued for transmission"), 1,
1551 GNUNET_NO);
1552 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1553 pending->importance = 0; /* FIXME */
1554 pending->timeout = expiration_time;
1555 prm = (struct PeerResultMessage *) &pending[1];
1556 pending->msg = &prm->header;
1557 prm->header.size = htons (msize);
1558 prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1559 prm->type = htonl (type);
1560 prm->put_path_length = htonl (put_path_length);
1561 prm->get_path_length = htonl (get_path_length);
1562 prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1563 prm->key = *key;
1564 paths = (struct GNUNET_PeerIdentity *) &prm[1];
1565 memcpy (paths, put_path,
1566 put_path_length * sizeof (struct GNUNET_PeerIdentity));
1567 memcpy (&paths[put_path_length], get_path,
1568 get_path_length * sizeof (struct GNUNET_PeerIdentity));
1569 memcpy (&paths[put_path_length + get_path_length], data, data_size);
1570 GNUNET_CONTAINER_DLL_insert (pi->head, pi->tail, pending);
1571 pi->pending_count++;
1572 process_peer_queue (pi);
1573} 836}
1574 837
1575 838
@@ -1605,251 +868,17 @@ handle_dht_p2p_put (void *cls,
1605 const struct GNUNET_PeerIdentity *peer, 868 const struct GNUNET_PeerIdentity *peer,
1606 const struct GNUNET_MessageHeader *message) 869 const struct GNUNET_MessageHeader *message)
1607{ 870{
1608 const struct PeerPutMessage *put; 871 /**
1609 const struct GNUNET_PeerIdentity *put_path; 872 1. Search the friend,finger and check your own id to find the closest
1610 const void *payload; 873 * predecessor the given key.
1611 uint32_t putlen; 874 2. If self then datache_store
1612 uint16_t msize; 875 3. If friend, then add to peer queue
1613 size_t payload_size; 876 4. If finger, then add to the peer queue of the first hop.Again the
1614 enum GNUNET_DHT_RouteOption options; 877 * same doubt,how does a peer when it is in handle_dht_p2p_put makes
1615 struct GNUNET_CONTAINER_BloomFilter *bf; 878 * a distinction weather it should do a lookup in routing table or finger or
1616 struct GNUNET_HashCode test_key; 879 * friend table.
1617 struct GNUNET_HashCode phash; 880 */
1618 881 return 0;
1619 msize = ntohs (message->size);
1620 if (msize < sizeof (struct PeerPutMessage))
1621 {
1622 GNUNET_break_op (0);
1623 return GNUNET_YES;
1624 }
1625 put = (const struct PeerPutMessage *) message;
1626 putlen = ntohl (put->put_path_length);
1627 if ((msize <
1628 sizeof (struct PeerPutMessage) +
1629 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
1630 (putlen >
1631 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
1632 {
1633 GNUNET_break_op (0);
1634 return GNUNET_YES;
1635 }
1636 GNUNET_STATISTICS_update (GDS_stats,
1637 gettext_noop ("# P2P PUT requests received"), 1,
1638 GNUNET_NO);
1639 GNUNET_STATISTICS_update (GDS_stats,
1640 gettext_noop ("# P2P PUT bytes received"), msize,
1641 GNUNET_NO);
1642 put_path = (const struct GNUNET_PeerIdentity *) &put[1];
1643 payload = &put_path[putlen];
1644 options = ntohl (put->options);
1645 payload_size =
1646 msize - (sizeof (struct PeerPutMessage) +
1647 putlen * sizeof (struct GNUNET_PeerIdentity));
1648 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PUT for `%s' from %s\n",
1649 GNUNET_h2s (&put->key), GNUNET_i2s (peer));
1650 GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash);
1651 if (GNUNET_YES == log_route_details_stderr)
1652 {
1653 char *tmp;
1654
1655 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
1656 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
1657 "XDHT PUT %s: %s->%s (%u, %u=>%u)\n",
1658 GNUNET_h2s (&put->key), GNUNET_i2s (peer), tmp,
1659 ntohl(put->hop_count),
1660 GNUNET_CRYPTO_hash_matching_bits (&phash, &put->key),
1661 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, &put->key)
1662 );
1663 GNUNET_free (tmp);
1664 }
1665 switch (GNUNET_BLOCK_get_key
1666 (GDS_block_context, ntohl (put->type), payload, payload_size,
1667 &test_key))
1668 {
1669 case GNUNET_YES:
1670 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
1671 {
1672 char *put_s = GNUNET_strdup (GNUNET_h2s (&put->key));
1673 GNUNET_break_op (0);
1674 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1675 "PUT with key `%s' for block with key %s\n",
1676 put_s, GNUNET_h2s (&test_key));
1677 GNUNET_free (put_s);
1678 return GNUNET_YES;
1679 }
1680 break;
1681 case GNUNET_NO:
1682 GNUNET_break_op (0);
1683 return GNUNET_YES;
1684 case GNUNET_SYSERR:
1685 /* cannot verify, good luck */
1686 break;
1687 }
1688 if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
1689 {
1690 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
1691 ntohl (put->type),
1692 NULL, /* query */
1693 NULL, 0, /* bloom filer */
1694 NULL, 0, /* xquery */
1695 payload, payload_size))
1696 {
1697 case GNUNET_BLOCK_EVALUATION_OK_MORE:
1698 case GNUNET_BLOCK_EVALUATION_OK_LAST:
1699 break;
1700
1701 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
1702 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
1703 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
1704 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
1705 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
1706 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
1707 default:
1708 GNUNET_break_op (0);
1709 return GNUNET_OK;
1710 }
1711 }
1712
1713 bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter, DHT_BLOOM_SIZE,
1714 GNUNET_CONSTANTS_BLOOMFILTER_K);
1715 GNUNET_break_op (GNUNET_YES ==
1716 GNUNET_CONTAINER_bloomfilter_test (bf, &phash));
1717 {
1718 struct GNUNET_PeerIdentity pp[putlen + 1];
1719
1720 /* extend 'put path' by sender */
1721 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1722 {
1723 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
1724 pp[putlen] = *peer;
1725 putlen++;
1726 }
1727 else
1728 putlen = 0;
1729
1730 /* give to local clients */
1731 GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (put->expiration_time),
1732 &put->key, 0, NULL, putlen, pp, ntohl (put->type),
1733 payload_size, payload);
1734 /* store locally */
1735 if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1736 (am_closest_peer (&put->key, bf)))
1737 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh
1738 (put->expiration_time), &put->key, putlen, pp,
1739 ntohl (put->type), payload_size, payload);
1740 /* route to other peers */
1741 GDS_NEIGHBOURS_handle_put (ntohl (put->type), options,
1742 ntohl (put->desired_replication_level),
1743 GNUNET_TIME_absolute_ntoh (put->expiration_time),
1744 ntohl (put->hop_count), bf, &put->key, putlen,
1745 pp, payload, payload_size);
1746 /* notify monitoring clients */
1747 GDS_CLIENTS_process_put (options,
1748 ntohl (put->type),
1749 ntohl (put->hop_count),
1750 ntohl (put->desired_replication_level),
1751 putlen, pp,
1752 GNUNET_TIME_absolute_ntoh (put->expiration_time),
1753 &put->key,
1754 payload,
1755 payload_size);
1756 }
1757 GNUNET_CONTAINER_bloomfilter_free (bf);
1758 return GNUNET_YES;
1759}
1760
1761
1762/**
1763 * We have received a FIND PEER request. Send matching
1764 * HELLOs back.
1765 *
1766 * @param sender sender of the FIND PEER request
1767 * @param key peers close to this key are desired
1768 * @param bf peers matching this bf are excluded
1769 * @param bf_mutator mutator for bf
1770 */
1771static void
1772handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1773 const struct GNUNET_HashCode * key,
1774 struct GNUNET_CONTAINER_BloomFilter *bf, uint32_t bf_mutator)
1775{
1776 int bucket_idx;
1777 struct PeerBucket *bucket;
1778 struct PeerInfo *peer;
1779 unsigned int choice;
1780 struct GNUNET_HashCode phash;
1781 struct GNUNET_HashCode mhash;
1782 const struct GNUNET_HELLO_Message *hello;
1783
1784 /* first, check about our own HELLO */
1785 if (NULL != GDS_my_hello)
1786 {
1787 GNUNET_BLOCK_mingle_hash (&my_identity_hash, bf_mutator, &mhash);
1788 if ((NULL == bf) ||
1789 (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)))
1790 {
1791 GDS_NEIGHBOURS_handle_reply (sender, GNUNET_BLOCK_TYPE_DHT_HELLO,
1792 GNUNET_TIME_relative_to_absolute
1793 (hello_expiration),
1794 key, 0, NULL, 0, NULL, GDS_my_hello,
1795 GNUNET_HELLO_size ((const struct
1796 GNUNET_HELLO_Message *)
1797 GDS_my_hello));
1798 }
1799 else
1800 {
1801 GNUNET_STATISTICS_update (GDS_stats,
1802 gettext_noop
1803 ("# FIND PEER requests ignored due to Bloomfilter"),
1804 1, GNUNET_NO);
1805 }
1806 }
1807 else
1808 {
1809 GNUNET_STATISTICS_update (GDS_stats,
1810 gettext_noop
1811 ("# FIND PEER requests ignored due to lack of HELLO"),
1812 1, GNUNET_NO);
1813 }
1814
1815 /* then, also consider sending a random HELLO from the closest bucket */
1816 if (0 == memcmp (&my_identity_hash, key, sizeof (struct GNUNET_HashCode)))
1817 bucket_idx = closest_bucket;
1818 else
1819 bucket_idx = GNUNET_MIN (closest_bucket, find_bucket (key));
1820 if (bucket_idx == GNUNET_SYSERR)
1821 return;
1822 bucket = &k_buckets[bucket_idx];
1823 if (bucket->peers_size == 0)
1824 return;
1825 choice =
1826 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, bucket->peers_size);
1827 peer = bucket->head;
1828 while (choice > 0)
1829 {
1830 GNUNET_assert (NULL != peer);
1831 peer = peer->next;
1832 choice--;
1833 }
1834 choice = bucket->peers_size;
1835 do
1836 {
1837 peer = peer->next;
1838 if (choice-- == 0)
1839 return; /* no non-masked peer available */
1840 if (peer == NULL)
1841 peer = bucket->head;
1842 GNUNET_CRYPTO_hash (&peer->id, sizeof (struct GNUNET_PeerIdentity), &phash);
1843 GNUNET_BLOCK_mingle_hash (&phash, bf_mutator, &mhash);
1844 hello = GDS_HELLO_get (&peer->id);
1845 }
1846 while ((hello == NULL) ||
1847 (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)));
1848 GDS_NEIGHBOURS_handle_reply (sender, GNUNET_BLOCK_TYPE_DHT_HELLO,
1849 GNUNET_TIME_relative_to_absolute
1850 (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION), key,
1851 0, NULL, 0, NULL, hello,
1852 GNUNET_HELLO_size (hello));
1853} 882}
1854 883
1855 884
@@ -1866,134 +895,7 @@ static int
1866handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, 895handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
1867 const struct GNUNET_MessageHeader *message) 896 const struct GNUNET_MessageHeader *message)
1868{ 897{
1869 struct PeerGetMessage *get; 898 return 0;
1870 uint32_t xquery_size;
1871 size_t reply_bf_size;
1872 uint16_t msize;
1873 enum GNUNET_BLOCK_Type type;
1874 enum GNUNET_DHT_RouteOption options;
1875 enum GNUNET_BLOCK_EvaluationResult eval;
1876 struct GNUNET_CONTAINER_BloomFilter *reply_bf;
1877 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
1878 const char *xquery;
1879 struct GNUNET_HashCode phash;
1880
1881 GNUNET_break (0 !=
1882 memcmp (peer, &my_identity,
1883 sizeof (struct GNUNET_PeerIdentity)));
1884 /* parse and validate message */
1885 msize = ntohs (message->size);
1886 if (msize < sizeof (struct PeerGetMessage))
1887 {
1888 GNUNET_break_op (0);
1889 return GNUNET_YES;
1890 }
1891 get = (struct PeerGetMessage *) message;
1892 xquery_size = ntohl (get->xquery_size);
1893 if (msize < sizeof (struct PeerGetMessage) + xquery_size)
1894 {
1895 GNUNET_break_op (0);
1896 return GNUNET_YES;
1897 }
1898 reply_bf_size = msize - (sizeof (struct PeerGetMessage) + xquery_size);
1899 type = ntohl (get->type);
1900 options = ntohl (get->options);
1901 xquery = (const char *) &get[1];
1902 reply_bf = NULL;
1903 GNUNET_STATISTICS_update (GDS_stats,
1904 gettext_noop ("# P2P GET requests received"), 1,
1905 GNUNET_NO);
1906 GNUNET_STATISTICS_update (GDS_stats,
1907 gettext_noop ("# P2P GET bytes received"), msize,
1908 GNUNET_NO);
1909 GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash);
1910 if (GNUNET_YES == log_route_details_stderr)
1911 {
1912 char *tmp;
1913
1914 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
1915 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
1916 "XDHT GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
1917 GNUNET_h2s (&get->key), GNUNET_i2s (peer), tmp,
1918 ntohl(get->hop_count),
1919 GNUNET_CRYPTO_hash_matching_bits (&phash, &get->key),
1920 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, &get->key),
1921 ntohl(get->xquery_size), xquery
1922 );
1923 GNUNET_free (tmp);
1924 }
1925
1926 if (reply_bf_size > 0)
1927 reply_bf =
1928 GNUNET_CONTAINER_bloomfilter_init (&xquery[xquery_size], reply_bf_size,
1929 GNUNET_CONSTANTS_BLOOMFILTER_K);
1930 eval =
1931 GNUNET_BLOCK_evaluate (GDS_block_context, type, &get->key, &reply_bf,
1932 get->bf_mutator, xquery, xquery_size, NULL, 0);
1933 if (eval != GNUNET_BLOCK_EVALUATION_REQUEST_VALID)
1934 {
1935 /* request invalid or block type not supported */
1936 GNUNET_break_op (eval == GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED);
1937 if (NULL != reply_bf)
1938 GNUNET_CONTAINER_bloomfilter_free (reply_bf);
1939 return GNUNET_YES;
1940 }
1941 peer_bf =
1942 GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter, DHT_BLOOM_SIZE,
1943 GNUNET_CONSTANTS_BLOOMFILTER_K);
1944 GNUNET_break_op (GNUNET_YES ==
1945 GNUNET_CONTAINER_bloomfilter_test (peer_bf,
1946 &phash));
1947 /* remember request for routing replies */
1948 GDS_ROUTING_add (peer, type, options, &get->key, xquery, xquery_size,
1949 reply_bf, get->bf_mutator);
1950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GET for %s at %s after %u hops\n",
1951 GNUNET_h2s (&get->key), GNUNET_i2s (&my_identity),
1952 (unsigned int) ntohl (get->hop_count));
1953 /* local lookup (this may update the reply_bf) */
1954 if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1955 (am_closest_peer (&get->key, peer_bf)))
1956 {
1957 if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
1958 {
1959 GNUNET_STATISTICS_update (GDS_stats,
1960 gettext_noop
1961 ("# P2P FIND PEER requests processed"), 1,
1962 GNUNET_NO);
1963 handle_find_peer (peer, &get->key, reply_bf, get->bf_mutator);
1964 }
1965 else
1966 {
1967 eval =
1968 GDS_DATACACHE_handle_get (&get->key, type, xquery, xquery_size,
1969 &reply_bf, get->bf_mutator);
1970 }
1971 }
1972 else
1973 {
1974 GNUNET_STATISTICS_update (GDS_stats,
1975 gettext_noop ("# P2P GET requests ONLY routed"),
1976 1, GNUNET_NO);
1977 }
1978
1979 GDS_CLIENTS_process_get (options,
1980 type,
1981 ntohl(get->hop_count),
1982 ntohl(get->desired_replication_level),
1983 0, NULL,
1984 &get->key);
1985
1986 /* P2P forwarding */
1987 if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
1988 GDS_NEIGHBOURS_handle_get (type, options,
1989 ntohl (get->desired_replication_level),
1990 ntohl (get->hop_count), &get->key, xquery,
1991 xquery_size, reply_bf, get->bf_mutator, peer_bf);
1992 /* clean up */
1993 if (NULL != reply_bf)
1994 GNUNET_CONTAINER_bloomfilter_free (reply_bf);
1995 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
1996 return GNUNET_YES;
1997} 899}
1998 900
1999 901
@@ -2009,184 +911,106 @@ static int
2009handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, 911handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer,
2010 const struct GNUNET_MessageHeader *message) 912 const struct GNUNET_MessageHeader *message)
2011{ 913{
2012 const struct PeerResultMessage *prm; 914 return 0;
2013 const struct GNUNET_PeerIdentity *put_path; 915}
2014 const struct GNUNET_PeerIdentity *get_path;
2015 const void *data;
2016 uint32_t get_path_length;
2017 uint32_t put_path_length;
2018 uint16_t msize;
2019 size_t data_size;
2020 enum GNUNET_BLOCK_Type type;
2021
2022 /* parse and validate message */
2023 msize = ntohs (message->size);
2024 if (msize < sizeof (struct PeerResultMessage))
2025 {
2026 GNUNET_break_op (0);
2027 return GNUNET_YES;
2028 }
2029 prm = (struct PeerResultMessage *) message;
2030 put_path_length = ntohl (prm->put_path_length);
2031 get_path_length = ntohl (prm->get_path_length);
2032 if ((msize <
2033 sizeof (struct PeerResultMessage) + (get_path_length +
2034 put_path_length) *
2035 sizeof (struct GNUNET_PeerIdentity)) ||
2036 (get_path_length >
2037 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
2038 (put_path_length >
2039 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
2040 {
2041 GNUNET_break_op (0);
2042 return GNUNET_YES;
2043 }
2044 put_path = (const struct GNUNET_PeerIdentity *) &prm[1];
2045 get_path = &put_path[put_path_length];
2046 type = ntohl (prm->type);
2047 data = (const void *) &get_path[get_path_length];
2048 data_size =
2049 msize - (sizeof (struct PeerResultMessage) +
2050 (get_path_length +
2051 put_path_length) * sizeof (struct GNUNET_PeerIdentity));
2052 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P RESULTS received"),
2053 1, GNUNET_NO);
2054 GNUNET_STATISTICS_update (GDS_stats,
2055 gettext_noop ("# P2P RESULT bytes received"),
2056 msize, GNUNET_NO);
2057 if (GNUNET_YES == log_route_details_stderr)
2058 {
2059 char *tmp;
2060 916
2061 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
2062 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "XDHT RESULT %s: %s->%s (%u)\n",
2063 GNUNET_h2s (&prm->key), GNUNET_i2s (peer), tmp,
2064 get_path_length + 1);
2065 GNUNET_free (tmp);
2066 }
2067 /* if we got a HELLO, consider it for our own routing table */
2068 if (type == GNUNET_BLOCK_TYPE_DHT_HELLO)
2069 {
2070 const struct GNUNET_MessageHeader *h;
2071 struct GNUNET_PeerIdentity pid;
2072 int bucket;
2073 917
2074 /* Should be a HELLO, validate and consider using it! */ 918/**
2075 if (data_size < sizeof (struct GNUNET_MessageHeader)) 919 * Read the trail setup message backwards to find which is the next hop to which
2076 { 920 * it should be send to.
2077 GNUNET_break_op (0); 921 * @return
2078 return GNUNET_YES; 922 */
2079 } 923//static
2080 h = data; 924struct GNUNET_PeerIdentity *
2081 if (data_size != ntohs (h->size)) 925find_next_hop()
2082 { 926{
2083 GNUNET_break_op (0); 927 return NULL;
2084 return GNUNET_YES; 928}
2085 }
2086 if (GNUNET_OK !=
2087 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h, &pid))
2088 {
2089 GNUNET_break_op (0);
2090 return GNUNET_YES;
2091 }
2092 if ((GNUNET_YES != disable_try_connect) &&
2093 0 != memcmp (&my_identity, &pid, sizeof (struct GNUNET_PeerIdentity)))
2094 {
2095 struct GNUNET_HashCode pid_hash;
2096
2097 GNUNET_CRYPTO_hash (&pid, sizeof (struct GNUNET_PeerIdentity), &pid_hash);
2098 bucket = find_bucket (&pid_hash);
2099 if ((bucket >= 0) &&
2100 (k_buckets[bucket].peers_size < bucket_size) &&
2101 (NULL != GDS_transport_handle))
2102 {
2103 GNUNET_TRANSPORT_offer_hello (GDS_transport_handle, h, NULL, NULL);
2104 GNUNET_TRANSPORT_try_connect (GDS_transport_handle, &pid, NULL, NULL); /*FIXME TRY_CONNECT change */
2105 }
2106 }
2107 }
2108 929
2109 /* append 'peer' to 'get_path' */
2110 {
2111 struct GNUNET_PeerIdentity xget_path[get_path_length + 1];
2112
2113 memcpy (xget_path, get_path,
2114 get_path_length * sizeof (struct GNUNET_PeerIdentity));
2115 xget_path[get_path_length] = *peer;
2116 get_path_length++;
2117
2118 /* forward to local clients */
2119 GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2120 &prm->key, get_path_length, xget_path,
2121 put_path_length, put_path, type, data_size, data);
2122 GDS_CLIENTS_process_get_resp (type,
2123 xget_path, get_path_length,
2124 put_path, put_path_length,
2125 GNUNET_TIME_absolute_ntoh (
2126 prm->expiration_time),
2127 &prm->key,
2128 data,
2129 data_size);
2130 if (GNUNET_YES == cache_results)
2131 {
2132 struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length];
2133 930
2134 memcpy (xput_path, put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); 931/**
2135 memcpy (&xput_path[put_path_length], 932 * Find the predecessor for given finger_id from the
2136 xget_path, 933 * friend and finger table.
2137 get_path_length * sizeof (struct GNUNET_PeerIdentity)); 934 * if friend, then just return the friend it
935 * if finger, then return the next hop to forward the packet to.
936 * @return
937 */
938//static
939struct GNUNET_PeerIdentity *
940find_predecessor()
941{
942 return NULL;
943}
2138 944
2139 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2140 &prm->key,
2141 get_path_length + put_path_length, xput_path,
2142 type, data_size, data);
2143 }
2144 /* forward to other peers */
2145 GDS_ROUTING_process (type, GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2146 &prm->key, put_path_length, put_path, get_path_length,
2147 xget_path, data, data_size);
2148 }
2149 945
2150 return GNUNET_YES; 946/**
947 * Core handler for P2P trail setup message.
948 */
949static int
950handle_dht_p2p_trail_setup()
951{
952 /*
953 * When we get this message from our friend then
954 * 1. Check the destination finger id that the message is looking for.
955 * 2. If my_identity = destination, then create a trail_setup_result message
956 * read the path taken to reach to you. read that list backwards to find which
957 * friend to forward this trailsetupresult to. find_next_hop()
958 * call process_peer_queue() to add trailsetupresult message to peer
959 * 3. If you are not the destination
960 * then call find_predecessor() to find closest finger to our given finger_id
961 * //GDS_ROUTING_ADD
962 * //GDS_ROUTING_FIND
963 *
964 */
965 return 0;
966
2151} 967}
2152 968
2153 969
2154/** 970/**
2155 * Initialize neighbours subsystem. 971 * Core handle for p2p trail construction result messages.
2156 * 972 *
973 * @return
974 */
975static int
976handle_dht_p2p_trail_setup_result()
977{
978 /*
979 Here you got a message that trail is set*/
980 return 0;
981}
982
983
984/**
985 * Initialize neighbours subsystem.
2157 * @return GNUNET_OK on success, GNUNET_SYSERR on error 986 * @return GNUNET_OK on success, GNUNET_SYSERR on error
2158 */ 987 */
2159int 988int
2160GDS_NEIGHBOURS_init () 989GDS_NEIGHBOURS_init()
2161{ 990{
2162 static struct GNUNET_CORE_MessageHandler core_handlers[] = { 991 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
2163 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0}, 992 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
2164 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0}, 993 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
2165 {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0}, 994 {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0},
995 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
996 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
2166 {NULL, 0, 0} 997 {NULL, 0, 0}
2167 }; 998 };
2168 unsigned long long temp_config_num; 999
2169
2170 disable_try_connect
2171 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, "DHT", "DISABLE_TRY_CONNECT");
2172 if (GNUNET_OK ==
2173 GNUNET_CONFIGURATION_get_value_number (GDS_cfg, "DHT", "bucket_size",
2174 &temp_config_num))
2175 bucket_size = (unsigned int) temp_config_num;
2176 cache_results
2177 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, "DHT", "CACHE_RESULTS");
2178
2179 log_route_details_stderr =
2180 (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO;
2181 atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL); 1000 atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL);
2182 core_api = 1001 core_api =
2183 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, 1002 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
2184 &handle_core_disconnect, NULL, GNUNET_NO, NULL, 1003 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
2185 GNUNET_NO, core_handlers); 1004 GNUNET_NO, core_handlers);
2186 if (core_api == NULL) 1005 if (core_api == NULL)
2187 return GNUNET_SYSERR; 1006 return GNUNET_SYSERR;
2188 all_known_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); 1007
1008 friend_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1009 finger_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1010
1011
2189 return GNUNET_OK; 1012 return GNUNET_OK;
1013
2190} 1014}
2191 1015
2192 1016
@@ -2202,16 +1026,23 @@ GDS_NEIGHBOURS_done ()
2202 core_api = NULL; 1026 core_api = NULL;
2203 GNUNET_ATS_performance_done (atsAPI); 1027 GNUNET_ATS_performance_done (atsAPI);
2204 atsAPI = NULL; 1028 atsAPI = NULL;
2205 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (all_known_peers)); 1029
2206 GNUNET_CONTAINER_multipeermap_destroy (all_known_peers); 1030 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peers));
2207 all_known_peers = NULL; 1031 GNUNET_CONTAINER_multipeermap_destroy (friend_peers);
2208 if (GNUNET_SCHEDULER_NO_TASK != find_peer_task) 1032 friend_peers = NULL;
1033
1034 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peers));
1035 GNUNET_CONTAINER_multipeermap_destroy (finger_peers);
1036 finger_peers = NULL;
1037
1038 if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
2209 { 1039 {
2210 GNUNET_SCHEDULER_cancel (find_peer_task); 1040 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
2211 find_peer_task = GNUNET_SCHEDULER_NO_TASK; 1041 find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
2212 } 1042 }
2213} 1043}
2214 1044
1045
2215/** 1046/**
2216 * Get the ID of the local node. 1047 * Get the ID of the local node.
2217 * 1048 *
@@ -2224,4 +1055,4 @@ GDS_NEIGHBOURS_get_id ()
2224} 1055}
2225 1056
2226 1057
2227/* end of gnunet-service-dht_neighbours.c */ 1058/* end of gnunet-service-xdht_neighbours.c */ \ No newline at end of file
diff --git a/src/dht/gnunet-service-xdht_neighbours.h b/src/dht/gnunet-service-xdht_neighbours.h
index a059d80fc..615db9198 100644
--- a/src/dht/gnunet-service-xdht_neighbours.h
+++ b/src/dht/gnunet-service-xdht_neighbours.h
@@ -32,94 +32,6 @@
32#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
33 33
34/** 34/**
35 * Perform a PUT operation. Forwards the given request to other
36 * peers. Does not store the data locally. Does not give the
37 * data to local clients. May do nothing if this is the only
38 * peer in the network (or if we are the closest peer in the
39 * network).
40 *
41 * @param type type of the block
42 * @param options routing options
43 * @param desired_replication_level desired replication level
44 * @param expiration_time when does the content expire
45 * @param hop_count how many hops has this message traversed so far
46 * @param bf Bloom filter of peers this PUT has already traversed
47 * @param key key for the content
48 * @param put_path_length number of entries in put_path
49 * @param put_path peers this request has traversed so far (if tracked)
50 * @param data payload to store
51 * @param data_size number of bytes in data
52 */
53void
54GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
55 enum GNUNET_DHT_RouteOption options,
56 uint32_t desired_replication_level,
57 struct GNUNET_TIME_Absolute expiration_time,
58 uint32_t hop_count,
59 struct GNUNET_CONTAINER_BloomFilter *bf,
60 const struct GNUNET_HashCode * key,
61 unsigned int put_path_length,
62 struct GNUNET_PeerIdentity *put_path,
63 const void *data, size_t data_size);
64
65
66/**
67 * Perform a GET operation. Forwards the given request to other
68 * peers. Does not lookup the key locally. May do nothing if this is
69 * the only peer in the network (or if we are the closest peer in the
70 * network).
71 *
72 * @param type type of the block
73 * @param options routing options
74 * @param desired_replication_level desired replication count
75 * @param hop_count how many hops did this request traverse so far?
76 * @param key key for the content
77 * @param xquery extended query
78 * @param xquery_size number of bytes in xquery
79 * @param reply_bf bloomfilter to filter duplicates
80 * @param reply_bf_mutator mutator for reply_bf
81 * @param peer_bf filter for peers not to select (again, updated)
82 */
83void
84GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
85 enum GNUNET_DHT_RouteOption options,
86 uint32_t desired_replication_level,
87 uint32_t hop_count, const struct GNUNET_HashCode * key,
88 const void *xquery, size_t xquery_size,
89 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
90 uint32_t reply_bf_mutator,
91 struct GNUNET_CONTAINER_BloomFilter *peer_bf);
92
93
94/**
95 * Handle a reply (route to origin). Only forwards the reply back to
96 * other peers waiting for it. Does not do local caching or
97 * forwarding to local clients.
98 *
99 * @param target neighbour that should receive the block (if still connected)
100 * @param type type of the block
101 * @param expiration_time when does the content expire
102 * @param key key for the content
103 * @param put_path_length number of entries in put_path
104 * @param put_path peers the original PUT traversed (if tracked)
105 * @param get_path_length number of entries in put_path
106 * @param get_path peers this reply has traversed so far (if tracked)
107 * @param data payload of the reply
108 * @param data_size number of bytes in data
109 */
110void
111GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
112 enum GNUNET_BLOCK_Type type,
113 struct GNUNET_TIME_Absolute expiration_time,
114 const struct GNUNET_HashCode * key,
115 unsigned int put_path_length,
116 const struct GNUNET_PeerIdentity *put_path,
117 unsigned int get_path_length,
118 const struct GNUNET_PeerIdentity *get_path,
119 const void *data, size_t data_size);
120
121
122/**
123 * Initialize neighbours subsystem. 35 * Initialize neighbours subsystem.
124 * 36 *
125 * @return GNUNET_OK on success, GNUNET_SYSERR on error 37 * @return GNUNET_OK on success, GNUNET_SYSERR on error
@@ -144,4 +56,4 @@ struct GNUNET_PeerIdentity *
144GDS_NEIGHBOURS_get_id (); 56GDS_NEIGHBOURS_get_id ();
145 57
146 58
147#endif 59#endif \ No newline at end of file
diff --git a/src/dht/gnunet-service-xdht_routing.c b/src/dht/gnunet-service-xdht_routing.c
index 83568e237..66ab88eb4 100644
--- a/src/dht/gnunet-service-xdht_routing.c
+++ b/src/dht/gnunet-service-xdht_routing.c
@@ -21,14 +21,17 @@
21/** 21/**
22 * @file dht/gnunet-service-xdht_routing.c 22 * @file dht/gnunet-service-xdht_routing.c
23 * @brief GNUnet DHT tracking of requests for routing replies 23 * @brief GNUnet DHT tracking of requests for routing replies
24 * @author Christian Grothoff 24 * @author Supriti Singh
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet-service-xdht_neighbours.h" 27#include "gnunet-service-xdht_neighbours.h"
28#include "gnunet-service-xdht_routing.h" 28#include "gnunet-service-xdht_routing.h"
29#include "gnunet-service-xdht.h" 29#include "gnunet-service-xdht.h"
30 30
31 31/* FIXME
32 * 1. We need field to understand which routing table is for which peer.
33 * 2. Better function names and variable names.
34 */
32/** 35/**
33 * Number of requests we track at most (for routing replies). 36 * Number of requests we track at most (for routing replies).
34 */ 37 */
@@ -36,223 +39,81 @@
36 39
37 40
38/** 41/**
39 * Information we keep about all recent GET requests 42 * Routing table entry .
40 * so that we can route replies.
41 */ 43 */
42struct RecentRequest 44struct RoutingTrail
43{ 45{
44 46 /**
45 /** 47 * Source peer .
46 * The peer this request was received from. 48 */
47 */ 49 struct GNUNET_PeerIdentity endpoint1;
48 struct GNUNET_PeerIdentity peer; 50
49 51 /**
50 /** 52 * Destination peer.
51 * Key of this request. 53 */
52 */ 54 struct GNUNET_PeerIdentity endppoint2;
53 struct GNUNET_HashCode key; 55
54 56 /**
55 /** 57 * The peer this request was received from.
56 * Position of this node in the min heap. 58 */
57 */ 59 struct GNUNET_PeerIdentity previous_hop;
58 struct GNUNET_CONTAINER_HeapNode *heap_node; 60
59 61 /**
60 /** 62 * The peer to which this request should be passed to.
61 * Bloomfilter for replies to drop. 63 */
62 */ 64 struct GNUNET_PeerIdentity next_hop;
63 struct GNUNET_CONTAINER_BloomFilter *reply_bf;
64
65 /**
66 * Type of the requested block.
67 */
68 enum GNUNET_BLOCK_Type type;
69
70 /**
71 * extended query (see gnunet_block_lib.h). Allocated at the
72 * end of this struct.
73 */
74 const void *xquery;
75
76 /**
77 * Number of bytes in xquery.
78 */
79 size_t xquery_size;
80
81 /**
82 * Mutator value for the reply_bf, see gnunet_block_lib.h
83 */
84 uint32_t reply_bf_mutator;
85
86 /**
87 * Request options.
88 */
89 enum GNUNET_DHT_RouteOption options;
90
91}; 65};
92 66
93 67
94/** 68/**
95 * Recent requests by time inserted. 69 * Routing table of the peer
96 */ 70 */
97static struct GNUNET_CONTAINER_Heap *recent_heap; 71static struct GNUNET_CONTAINER_MultiPeerMap *routing_table;
98
99/**
100 * Recently seen requests by key.
101 */
102static struct GNUNET_CONTAINER_MultiHashMap *recent_map;
103 72
104 73
105/** 74/**
106 * Closure for the 'process' function. 75 * Find the next hop to pass the message to .
76 * @return
107 */ 77 */
108struct ProcessContext 78//static struct GNUNET_PeerIdentity *
109{ 79//find_next_hop()
110 /** 80//{
111 * Path of the original PUT 81
112 */ 82//}
113 const struct GNUNET_PeerIdentity *put_path;
114
115 /**
116 * Path of the reply.
117 */
118 const struct GNUNET_PeerIdentity *get_path;
119
120 /**
121 * Payload of the reply.
122 */
123 const void *data;
124 83
125 /**
126 * Expiration time of the result.
127 */
128 struct GNUNET_TIME_Absolute expiration_time;
129
130 /**
131 * Number of entries in 'put_path'.
132 */
133 unsigned int put_path_length;
134
135 /**
136 * Number of entries in 'get_path'.
137 */
138 unsigned int get_path_length;
139
140 /**
141 * Number of bytes in 'data'.
142 */
143 size_t data_size;
144
145 /**
146 * Type of the reply.
147 */
148 enum GNUNET_BLOCK_Type type;
149
150};
151 84
152 85
153/** 86/**
154 * Forward the result to the given peer if it matches the request. 87 * Add a new entry to our routing table.
155 * 88 *
156 * @param cls the `struct ProcessContext` with the result 89 * @param sender peer that originated the request
157 * @param key the query 90 * @param type type of the block
158 * @param value the `struct RecentRequest` with the request 91 * @param options options for processing
159 * @return #GNUNET_OK (continue to iterate), 92 * @param key key for the content
160 * #GNUNET_SYSERR if the result is malformed or type unsupported 93 * @param xquery extended query
94 * @param xquery_size number of bytes in @a xquery
95 * @param reply_bf bloomfilter to filter duplicates
96 * @param reply_bf_mutator mutator for @a reply_bf
161 */ 97 */
162static int 98void
163process (void *cls, const struct GNUNET_HashCode * key, void *value) 99GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
100 enum GNUNET_BLOCK_Type type,
101 enum GNUNET_DHT_RouteOption options,
102 const struct GNUNET_HashCode * key, const void *xquery,
103 size_t xquery_size,
104 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
105 uint32_t reply_bf_mutator)
164{ 106{
165 struct ProcessContext *pc = cls;
166 struct RecentRequest *rr = value;
167 enum GNUNET_BLOCK_EvaluationResult eval;
168 unsigned int gpl;
169 unsigned int ppl;
170 struct GNUNET_HashCode hc;
171 const struct GNUNET_HashCode *eval_key;
172
173 if ((rr->type != GNUNET_BLOCK_TYPE_ANY) && (rr->type != pc->type))
174 return GNUNET_OK; /* type missmatch */
175 107
176 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
177 {
178 gpl = pc->get_path_length;
179 ppl = pc->put_path_length;
180 }
181 else
182 {
183 gpl = 0;
184 ppl = 0;
185 }
186 if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
187 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO))
188 {
189 /* key may not match HELLO, which is OK since
190 * the search is approximate. Still, the evaluation
191 * would fail since the match is not exact. So
192 * we fake it by changing the key to the actual PID ... */
193 GNUNET_BLOCK_get_key (GDS_block_context, GNUNET_BLOCK_TYPE_DHT_HELLO,
194 pc->data, pc->data_size, &hc);
195 eval_key = &hc;
196 }
197 else
198 {
199 eval_key = key;
200 }
201 eval =
202 GNUNET_BLOCK_evaluate (GDS_block_context, pc->type, eval_key,
203 &rr->reply_bf, rr->reply_bf_mutator, rr->xquery,
204 rr->xquery_size, pc->data, pc->data_size);
205 switch (eval)
206 {
207 case GNUNET_BLOCK_EVALUATION_OK_MORE:
208 case GNUNET_BLOCK_EVALUATION_OK_LAST:
209 GNUNET_STATISTICS_update (GDS_stats,
210 gettext_noop
211 ("# Good REPLIES matched against routing table"),
212 1, GNUNET_NO);
213 GDS_NEIGHBOURS_handle_reply (&rr->peer, pc->type, pc->expiration_time, key,
214 ppl, pc->put_path, gpl, pc->get_path, pc->data,
215 pc->data_size);
216 break;
217 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
218 GNUNET_STATISTICS_update (GDS_stats,
219 gettext_noop
220 ("# Duplicate REPLIES matched against routing table"),
221 1, GNUNET_NO);
222 return GNUNET_OK;
223 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
224 GNUNET_STATISTICS_update (GDS_stats,
225 gettext_noop
226 ("# Invalid REPLIES matched against routing table"),
227 1, GNUNET_NO);
228 return GNUNET_SYSERR;
229 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
230 GNUNET_STATISTICS_update (GDS_stats,
231 gettext_noop
232 ("# Irrelevant REPLIES matched against routing table"),
233 1, GNUNET_NO);
234 return GNUNET_OK;
235 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
236 GNUNET_break (0);
237 return GNUNET_OK;
238 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
239 GNUNET_break (0);
240 return GNUNET_OK;
241 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
242 GNUNET_STATISTICS_update (GDS_stats,
243 gettext_noop
244 ("# Unsupported REPLIES matched against routing table"),
245 1, GNUNET_NO);
246 return GNUNET_SYSERR;
247 default:
248 GNUNET_break (0);
249 return GNUNET_SYSERR;
250 }
251 return GNUNET_OK;
252} 108}
253 109
110/* search in routing table for next hop to pass the message to .
111 * struct GNUNET_PeerIdentity *
112GDS_Routing_search()
113{
114}*/
254 115
255/** 116/**FIXME: Old implementation just to remove error
256 * Handle a reply (route to origin). Only forwards the reply back to 117 * Handle a reply (route to origin). Only forwards the reply back to
257 * other peers waiting for it. Does not do local caching or 118 * other peers waiting for it. Does not do local caching or
258 * forwarding to local clients. Essentially calls 119 * forwarding to local clients. Essentially calls
@@ -278,164 +139,14 @@ GDS_ROUTING_process (enum GNUNET_BLOCK_Type type,
278 const struct GNUNET_PeerIdentity *get_path, 139 const struct GNUNET_PeerIdentity *get_path,
279 const void *data, size_t data_size) 140 const void *data, size_t data_size)
280{ 141{
281 struct ProcessContext pc;
282
283 pc.type = type;
284 pc.expiration_time = expiration_time;
285 pc.put_path_length = put_path_length;
286 pc.put_path = put_path;
287 pc.get_path_length = get_path_length;
288 pc.get_path = get_path;
289 pc.data = data;
290 pc.data_size = data_size;
291 if (NULL == data)
292 {
293 /* Some apps might have an 'empty' reply as a valid reply; however,
294 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL'
295 reply as request-validation (but we need response-validation).
296 So we set 'data' to a 0-byte non-NULL value just to be sure */
297 GNUNET_break (0 == data_size);
298 pc.data_size = 0;
299 pc.data = ""; /* something not null */
300 }
301 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &process, &pc);
302} 142}
303
304
305/**
306 * Remove the oldest entry from the DHT routing table. Must only
307 * be called if it is known that there is at least one entry
308 * in the heap and hashmap.
309 */
310static void
311expire_oldest_entry ()
312{
313 struct RecentRequest *recent_req;
314
315 GNUNET_STATISTICS_update (GDS_stats,
316 gettext_noop
317 ("# Entries removed from routing table"), 1,
318 GNUNET_NO);
319 recent_req = GNUNET_CONTAINER_heap_peek (recent_heap);
320 GNUNET_assert (recent_req != NULL);
321 GNUNET_CONTAINER_heap_remove_node (recent_req->heap_node);
322 GNUNET_CONTAINER_bloomfilter_free (recent_req->reply_bf);
323 GNUNET_assert (GNUNET_YES ==
324 GNUNET_CONTAINER_multihashmap_remove (recent_map,
325 &recent_req->key,
326 recent_req));
327 GNUNET_free (recent_req);
328}
329
330
331/**
332 * Try to combine multiple recent requests for the same value
333 * (if they come from the same peer).
334 *
335 * @param cls the new 'struct RecentRequest' (to discard upon successful combination)
336 * @param key the query
337 * @param value the existing 'struct RecentRequest' (to update upon successful combination)
338 * @return GNUNET_OK (continue to iterate),
339 * GNUNET_SYSERR if the request was successfully combined
340 */
341static int
342try_combine_recent (void *cls, const struct GNUNET_HashCode * key, void *value)
343{
344 struct RecentRequest *in = cls;
345 struct RecentRequest *rr = value;
346
347 if ( (0 != memcmp (&in->peer,
348 &rr->peer,
349 sizeof (struct GNUNET_PeerIdentity))) ||
350 (in->type != rr->type) ||
351 (in->xquery_size != rr->xquery_size) ||
352 (0 != memcmp (in->xquery,
353 rr->xquery,
354 in->xquery_size)) )
355 return GNUNET_OK;
356 if (in->reply_bf_mutator != rr->reply_bf_mutator)
357 {
358 rr->reply_bf_mutator = in->reply_bf_mutator;
359 GNUNET_CONTAINER_bloomfilter_free (rr->reply_bf);
360 rr->reply_bf = in->reply_bf;
361 }
362 else
363 {
364 GNUNET_CONTAINER_bloomfilter_or2 (rr->reply_bf,
365 in->reply_bf);
366 GNUNET_CONTAINER_bloomfilter_free (in->reply_bf);
367 }
368 GNUNET_free (in);
369 return GNUNET_SYSERR;
370}
371
372
373/**
374 * Add a new entry to our routing table.
375 *
376 * @param sender peer that originated the request
377 * @param type type of the block
378 * @param options options for processing
379 * @param key key for the content
380 * @param xquery extended query
381 * @param xquery_size number of bytes in @a xquery
382 * @param reply_bf bloomfilter to filter duplicates
383 * @param reply_bf_mutator mutator for @a reply_bf
384 */
385void
386GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
387 enum GNUNET_BLOCK_Type type,
388 enum GNUNET_DHT_RouteOption options,
389 const struct GNUNET_HashCode * key, const void *xquery,
390 size_t xquery_size,
391 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
392 uint32_t reply_bf_mutator)
393{
394 struct RecentRequest *recent_req;
395
396 while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT)
397 expire_oldest_entry ();
398 GNUNET_STATISTICS_update (GDS_stats,
399 gettext_noop ("# Entries added to routing table"),
400 1, GNUNET_NO);
401 recent_req = GNUNET_malloc (sizeof (struct RecentRequest) + xquery_size);
402 recent_req->peer = *sender;
403 recent_req->key = *key;
404 recent_req->reply_bf = GNUNET_CONTAINER_bloomfilter_copy (reply_bf);
405 recent_req->type = type;
406 recent_req->options = options;
407 recent_req->xquery = &recent_req[1];
408 memcpy (&recent_req[1], xquery, xquery_size);
409 recent_req->xquery_size = xquery_size;
410 recent_req->reply_bf_mutator = reply_bf_mutator;
411 if (GNUNET_SYSERR ==
412 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key,
413 &try_combine_recent, recent_req))
414 {
415 GNUNET_STATISTICS_update (GDS_stats,
416 gettext_noop
417 ("# DHT requests combined"),
418 1, GNUNET_NO);
419 return;
420 }
421 recent_req->heap_node =
422 GNUNET_CONTAINER_heap_insert (recent_heap, recent_req,
423 GNUNET_TIME_absolute_get ().abs_value_us);
424 GNUNET_CONTAINER_multihashmap_put (recent_map, key, recent_req,
425 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
426
427
428}
429
430
431/** 143/**
432 * Initialize routing subsystem. 144 * Initialize routing subsystem.
433 */ 145 */
434void 146void
435GDS_ROUTING_init () 147GDS_ROUTING_init ()
436{ 148{
437 recent_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 149 routing_table = GNUNET_CONTAINER_multipeermap_create (DHT_MAX_RECENT * 4 / 3, GNUNET_NO);
438 recent_map = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT * 4 / 3, GNUNET_NO);
439} 150}
440 151
441 152
@@ -445,14 +156,8 @@ GDS_ROUTING_init ()
445void 156void
446GDS_ROUTING_done () 157GDS_ROUTING_done ()
447{ 158{
448 while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) 159 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (routing_table));
449 expire_oldest_entry (); 160 GNUNET_CONTAINER_multipeermap_destroy (routing_table);
450 GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap));
451 GNUNET_CONTAINER_heap_destroy (recent_heap);
452 recent_heap = NULL;
453 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map));
454 GNUNET_CONTAINER_multihashmap_destroy (recent_map);
455 recent_map = NULL;
456} 161}
457 162
458/* end of gnunet-service-dht_routing.c */ 163/* end of gnunet-service-xdht_routing.c */ \ No newline at end of file
diff --git a/src/dht/gnunet-service-xdht_routing.h b/src/dht/gnunet-service-xdht_routing.h
index 25605dcb4..a6c3281e9 100644
--- a/src/dht/gnunet-service-xdht_routing.h
+++ b/src/dht/gnunet-service-xdht_routing.h
@@ -32,33 +32,6 @@
32 32
33 33
34/** 34/**
35 * Handle a reply (route to origin). Only forwards the reply back to
36 * other peers waiting for it. Does not do local caching or
37 * forwarding to local clients. Essentially calls
38 * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching
39 * request recently.
40 *
41 * @param type type of the block
42 * @param expiration_time when does the content expire
43 * @param key key for the content
44 * @param put_path_length number of entries in @a put_path
45 * @param put_path peers the original PUT traversed (if tracked)
46 * @param get_path_length number of entries in @a get_path
47 * @param get_path peers this reply has traversed so far (if tracked)
48 * @param data payload of the reply
49 * @param data_size number of bytes in @a data
50 */
51void
52GDS_ROUTING_process (enum GNUNET_BLOCK_Type type,
53 struct GNUNET_TIME_Absolute expiration_time,
54 const struct GNUNET_HashCode * key, unsigned int put_path_length,
55 const struct GNUNET_PeerIdentity *put_path,
56 unsigned int get_path_length,
57 const struct GNUNET_PeerIdentity *get_path,
58 const void *data, size_t data_size);
59
60
61/**
62 * Add a new entry to our routing table. 35 * Add a new entry to our routing table.
63 * 36 *
64 * @param sender peer that originated the request 37 * @param sender peer that originated the request
@@ -80,6 +53,7 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
80 uint32_t reply_bf_mutator); 53 uint32_t reply_bf_mutator);
81 54
82 55
56
83/** 57/**
84 * Initialize routing subsystem. 58 * Initialize routing subsystem.
85 */ 59 */
diff --git a/src/dht/test_dht_api.c b/src/dht/test_dht_api.c
index 2295866d3..5c6913740 100644
--- a/src/dht/test_dht_api.c
+++ b/src/dht/test_dht_api.c
@@ -203,6 +203,7 @@ run (void *cls,
203 (GNUNET_TIME_UNIT_MINUTES, 1), &end_badly, 203 (GNUNET_TIME_UNIT_MINUTES, 1), &end_badly,
204 NULL); 204 NULL);
205 205
206
206 memset (&hash, 42, sizeof (struct GNUNET_HashCode)); 207 memset (&hash, 42, sizeof (struct GNUNET_HashCode));
207 data = GNUNET_malloc (data_size); 208 data = GNUNET_malloc (data_size);
208 memset (data, 43, data_size); 209 memset (data, 43, data_size);
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index e4423f145..2a0ca33b2 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -376,7 +376,7 @@ GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
376 }\ 376 }\
377} while (0) 377} while (0)
378 378
379#define GNUNET_log(kind,...) do { int log_line = __LINE__;\ 379 #define GNUNET_log(kind,...) do { int log_line = __LINE__;\
380 static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\ 380 static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
381 if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) { \ 381 if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) { \
382 if (GN_UNLIKELY(log_call_enabled == -1))\ 382 if (GN_UNLIKELY(log_call_enabled == -1))\
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index ee8a1272c..2a69e3029 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -606,6 +606,15 @@ extern "C"
606 */ 606 */
607#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156 607#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156
608 608
609/**
610 * Trail setup request is received by a peer.
611 */
612#define GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP 157
613
614/**
615 * Trail to a particular peer is returned to this peer.
616 */
617#define GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT 158
609 618
610/******************************************************************************* 619/*******************************************************************************
611 * HOSTLIST message types 620 * HOSTLIST message types
diff --git a/src/statistics/test_statistics_api_data.conf b/src/statistics/test_statistics_api_data.conf
index 572f51d71..e458f08bf 100644
--- a/src/statistics/test_statistics_api_data.conf
+++ b/src/statistics/test_statistics_api_data.conf
@@ -1,6 +1,7 @@
1[PATHS] 1[PATHS]
2GNUNET_TEST_HOME = /tmp/test-gnunet-statistics/ 2GNUNET_TEST_HOME = /tmp/test-gnunet-statistics/
3 3
4
4[statistics] 5[statistics]
5PORT = 22353 6PORT = 22353
6UNIXPATH = $GNUNET_RUNTIME_DIR/test-statistics-service-statistics.unix 7UNIXPATH = $GNUNET_RUNTIME_DIR/test-statistics-service-statistics.unix