nicer
[oweals/gnunet.git] / src / dht / gnunet-service-dht_neighbours.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file dht/gnunet-service-dht_neighbours.c
23  * @brief GNUnet DHT service's bucket and neighbour management code
24  * @author Christian Grothoff
25  * @author Nathan Evans
26  */
27
28 #include "platform.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_hello_lib.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_nse_service.h"
35 #include "gnunet_core_service.h"
36 #include "gnunet_datacache_lib.h"
37 #include "gnunet_transport_service.h"
38 #include "gnunet_hello_lib.h"
39 #include "gnunet_dht_service.h"
40 #include "gnunet_statistics_service.h"
41 #include "gnunet-service-dht.h"
42 #include "gnunet-service-dht_clients.h"
43 #include "gnunet-service-dht_datacache.h"
44 #include "gnunet-service-dht_hello.h"
45 #include "gnunet-service-dht_neighbours.h"
46 #include "gnunet-service-dht_nse.h"
47 #include "gnunet-service-dht_routing.h"
48 #include <fenv.h>
49 #include "dht.h"
50
51 /**
52  * How many buckets will we allow total.
53  */
54 #define MAX_BUCKETS sizeof (GNUNET_HashCode) * 8
55
56 /**
57  * What is the maximum number of peers in a given bucket.
58  */
59 #define DEFAULT_BUCKET_SIZE 4
60
61 /**
62  * Desired replication level for FIND PEER requests
63  */
64 #define FIND_PEER_REPLICATION_LEVEL 4
65
66 /**
67  * Maximum allowed replication level for all requests.
68  */
69 #define MAXIMUM_REPLICATION_LEVEL 16
70
71 /**
72  * How often to update our preference levels for peers in our routing tables.
73  */
74 #define DHT_DEFAULT_PREFERENCE_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
75
76 /**
77  * How long at least to wait before sending another find peer request.
78  */
79 #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
80
81 /**
82  * How long at most to wait before sending another find peer request.
83  */
84 #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 8)
85
86 /**
87  * How long at most to wait for transmission of a GET request to another peer?
88  */
89 #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
90
91
92 /**
93  * P2P PUT message
94  */
95 struct PeerPutMessage
96 {
97   /**
98    * Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
99    */
100   struct GNUNET_MessageHeader header;
101
102   /**
103    * Processing options
104    */
105   uint32_t options GNUNET_PACKED;
106
107   /**
108    * Content type.
109    */
110   uint32_t type GNUNET_PACKED;
111
112   /**
113    * Hop count
114    */
115   uint32_t hop_count GNUNET_PACKED;
116
117   /**
118    * Replication level for this message
119    */
120   uint32_t desired_replication_level GNUNET_PACKED;
121
122   /**
123    * Length of the PUT path that follows (if tracked).
124    */
125   uint32_t put_path_length GNUNET_PACKED;
126
127   /**
128    * When does the content expire?
129    */
130   struct GNUNET_TIME_AbsoluteNBO expiration_time;
131
132   /**
133    * Bloomfilter (for peer identities) to stop circular routes
134    */
135   char bloomfilter[DHT_BLOOM_SIZE];
136
137   /**
138    * The key we are storing under.
139    */
140   GNUNET_HashCode key;
141
142   /* put path (if tracked) */
143
144   /* Payload */
145
146 };
147
148
149 /**
150  * P2P Result message
151  */
152 struct PeerResultMessage
153 {
154   /**
155    * Type: GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
156    */
157   struct GNUNET_MessageHeader header;
158
159   /**
160    * Content type.
161    */
162   uint32_t type GNUNET_PACKED;
163
164   /**
165    * Length of the PUT path that follows (if tracked).
166    */
167   uint32_t put_path_length GNUNET_PACKED;
168
169   /**
170    * Length of the GET path that follows (if tracked).
171    */
172   uint32_t get_path_length GNUNET_PACKED;
173
174   /**
175    * When does the content expire?
176    */
177   struct GNUNET_TIME_AbsoluteNBO expiration_time;
178
179   /**
180    * The key of the corresponding GET request.
181    */
182   GNUNET_HashCode key;
183
184   /* put path (if tracked) */
185
186   /* get path (if tracked) */
187
188   /* Payload */
189
190 };
191
192
193 /**
194  * P2P GET message
195  */
196 struct PeerGetMessage
197 {
198   /**
199    * Type: GNUNET_MESSAGE_TYPE_DHT_P2P_GET
200    */
201   struct GNUNET_MessageHeader header;
202
203   /**
204    * Processing options
205    */
206   uint32_t options GNUNET_PACKED;
207
208   /**
209    * Desired content type.
210    */
211   uint32_t type GNUNET_PACKED;
212
213   /**
214    * Hop count
215    */
216   uint32_t hop_count GNUNET_PACKED;
217
218   /**
219    * Desired replication level for this request.
220    */
221   uint32_t desired_replication_level GNUNET_PACKED;
222
223   /**
224    * Size of the extended query.
225    */
226   uint32_t xquery_size;
227
228   /**
229    * Bloomfilter mutator.
230    */
231   uint32_t bf_mutator;
232
233   /**
234    * Bloomfilter (for peer identities) to stop circular routes
235    */
236   char bloomfilter[DHT_BLOOM_SIZE];
237
238   /**
239    * The key we are looking for.
240    */
241   GNUNET_HashCode key;
242
243   /* xquery */
244
245   /* result bloomfilter */
246
247 };
248
249
250 /**
251  * Linked list of messages to send to a particular other peer.
252  */
253 struct P2PPendingMessage
254 {
255   /**
256    * Pointer to next item in the list
257    */
258   struct P2PPendingMessage *next;
259
260   /**
261    * Pointer to previous item in the list
262    */
263   struct P2PPendingMessage *prev;
264
265   /**
266    * Message importance level.  FIXME: used? useful?
267    */
268   unsigned int importance;
269
270   /**
271    * When does this message time out?
272    */
273   struct GNUNET_TIME_Absolute timeout;
274
275   /**
276    * Actual message to be sent, allocated at the end of the struct:
277    * // msg = (cast) &pm[1]; 
278    * // memcpy (&pm[1], data, len);
279    */
280   const struct GNUNET_MessageHeader *msg;
281
282 };
283
284
285 /**
286  * Entry for a peer in a bucket.
287  */
288 struct PeerInfo
289 {
290   /**
291    * Next peer entry (DLL)
292    */
293   struct PeerInfo *next;
294
295   /**
296    *  Prev peer entry (DLL)
297    */
298   struct PeerInfo *prev;
299
300   /**
301    * Count of outstanding messages for peer.  FIXME: NEEDED?
302    * FIXME: bound queue size!?
303    */
304   unsigned int pending_count;
305
306   /**
307    * Head of pending messages to be sent to this peer.
308    */
309   struct P2PPendingMessage *head;
310
311   /**
312    * Tail of pending messages to be sent to this peer.
313    */
314   struct P2PPendingMessage *tail;
315
316   /**
317    * Core handle for sending messages to this peer.
318    */
319   struct GNUNET_CORE_TransmitHandle *th;
320
321   /**
322    * Preference update context
323    */
324   struct GNUNET_CORE_InformationRequestContext *info_ctx;
325
326   /**
327    * Task for scheduling preference updates
328    */
329   GNUNET_SCHEDULER_TaskIdentifier preference_task;
330
331   /**
332    * What is the identity of the peer?
333    */
334   struct GNUNET_PeerIdentity id;
335
336 #if 0
337   /**
338    * What is the average latency for replies received?
339    */
340   struct GNUNET_TIME_Relative latency;
341
342   /**
343    * Transport level distance to peer.
344    */
345   unsigned int distance;
346 #endif
347
348 };
349
350
351 /**
352  * Peers are grouped into buckets.
353  */
354 struct PeerBucket
355 {
356   /**
357    * Head of DLL
358    */
359   struct PeerInfo *head;
360
361   /**
362    * Tail of DLL
363    */
364   struct PeerInfo *tail;
365
366   /**
367    * Number of peers in the bucket.
368    */
369   unsigned int peers_size;
370 };
371
372
373 /**
374  * The lowest currently used bucket, initially 0 (for 0-bits matching bucket).
375  */
376 static unsigned int closest_bucket;
377
378 /**
379  * How many peers have we added since we sent out our last
380  * find peer request?
381  */
382 static unsigned int newly_found_peers;
383
384 /**
385  * The buckets.  Array of size MAX_BUCKET_SIZE.  Offset 0 means 0 bits matching.
386  */
387 static struct PeerBucket k_buckets[MAX_BUCKETS];
388
389 /**
390  * Hash map of all known peers, for easy removal from k_buckets on disconnect.
391  */
392 static struct GNUNET_CONTAINER_MultiHashMap *all_known_peers;
393
394 /**
395  * Maximum size for each bucket.
396  */
397 static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
398
399 /**
400  * Task that sends FIND PEER requests.
401  */
402 static GNUNET_SCHEDULER_TaskIdentifier find_peer_task;
403
404 /**
405  * Identity of this peer.
406  */ 
407 static struct GNUNET_PeerIdentity my_identity;
408
409 /**
410  * Handle to GNUnet core.
411  */
412 static struct GNUNET_CORE_Handle *coreAPI;
413
414
415 /**
416  * Find the optimal bucket for this key.
417  *
418  * @param hc the hashcode to compare our identity to
419  * @return the proper bucket index, or GNUNET_SYSERR
420  *         on error (same hashcode)
421  */
422 static int
423 find_bucket (const GNUNET_HashCode * hc)
424 {
425   unsigned int bits;
426
427   bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey, hc);
428   if (bits == MAX_BUCKETS)
429     {
430       /* How can all bits match? Got my own ID? */
431       GNUNET_break (0);
432       return GNUNET_SYSERR; 
433     }
434   return MAX_BUCKETS - bits - 1;
435 }
436
437
438 /**
439  * Let GNUnet core know that we like the given peer.
440  *
441  * @param cls the 'struct PeerInfo' of the peer
442  * @param tc scheduler context.
443  */ 
444 static void
445 update_core_preference (void *cls,
446                         const struct GNUNET_SCHEDULER_TaskContext *tc);
447
448
449 /**
450  * Function called with statistics about the given peer.
451  *
452  * @param cls closure
453  * @param peer identifies the peer
454  * @param bpm_out set to the current bandwidth limit (sending) for this peer
455  * @param amount set to the amount that was actually reserved or unreserved;
456  *               either the full requested amount or zero (no partial reservations)
457  * @param res_delay if the reservation could not be satisfied (amount was 0), how
458  *        long should the client wait until re-trying?
459  * @param preference current traffic preference for the given peer
460  */
461 static void
462 update_core_preference_finish (void *cls,
463                                const struct GNUNET_PeerIdentity *peer,
464                                struct GNUNET_BANDWIDTH_Value32NBO bpm_out,
465                                int32_t amount,
466                                struct GNUNET_TIME_Relative res_delay,
467                                uint64_t preference)
468 {
469   struct PeerInfo *peer_info = cls;
470
471   peer_info->info_ctx = NULL;
472   peer_info->preference_task
473     = GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL,
474                                     &update_core_preference, peer_info);
475 }
476
477
478 /**
479  * Let GNUnet core know that we like the given peer.
480  *
481  * @param cls the 'struct PeerInfo' of the peer
482  * @param tc scheduler context.
483  */ 
484 static void
485 update_core_preference (void *cls,
486                         const struct GNUNET_SCHEDULER_TaskContext *tc)
487 {
488   struct PeerInfo *peer = cls;
489   uint64_t preference;
490   unsigned int matching;
491   int bucket;
492
493   peer->preference_task = GNUNET_SCHEDULER_NO_TASK;
494   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
495     return;  
496   matching =
497     GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey,
498                                       &peer->id.hashPubKey);
499   if (matching >= 64)
500     matching = 63;
501   bucket = find_bucket (&peer->id.hashPubKey);
502   if (bucket == GNUNET_SYSERR)
503     preference = 0;
504   else
505     preference = (1LL << matching) / k_buckets[bucket].peers_size;
506   if (preference == 0)
507     {
508       peer->preference_task
509         = GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL,
510                                         &update_core_preference, peer);
511       return;
512     }
513   GNUNET_STATISTICS_update (GDS_stats,
514                             gettext_noop ("# Preference updates given to core"), 1,
515                             GNUNET_NO);
516   peer->info_ctx =
517     GNUNET_CORE_peer_change_preference (coreAPI, &peer->id,
518                                         GNUNET_TIME_UNIT_FOREVER_REL,
519                                         GNUNET_BANDWIDTH_VALUE_MAX, 0,
520                                         preference,
521                                         &update_core_preference_finish, peer);
522 }
523
524
525 /**
526  * Closure for 'add_known_to_bloom'.
527  */
528 struct BloomConstructorContext
529 {
530   /**
531    * Bloom filter under construction.
532    */
533   struct GNUNET_CONTAINER_BloomFilter *bloom;
534
535   /**
536    * Mutator to use.
537    */
538   uint32_t bf_mutator;
539 };
540
541
542 /**
543  * Add each of the peers we already know to the bloom filter of
544  * the request so that we don't get duplicate HELLOs.
545  *
546  * @param cls the 'struct BloomConstructorContext'.
547  * @param key peer identity to add to the bloom filter
548  * @param value value the peer information (unused)
549  * @return GNUNET_YES (we should continue to iterate)
550  */
551 static int
552 add_known_to_bloom (void *cls, const GNUNET_HashCode * key, void *value)
553 {
554   struct BloomConstructorContext *ctx = cls;
555   GNUNET_HashCode mh;
556
557   GNUNET_BLOCK_mingle_hash (key, ctx->bf_mutator, &mh);
558   GNUNET_CONTAINER_bloomfilter_add (ctx->bloom, &mh);
559   return GNUNET_YES;
560 }
561
562
563 /**
564  * Task to send a find peer message for our own peer identifier
565  * so that we can find the closest peers in the network to ourselves
566  * and attempt to connect to them.
567  *
568  * @param cls closure for this task
569  * @param tc the context under which the task is running
570  */
571 static void
572 send_find_peer_message (void *cls,
573                         const struct GNUNET_SCHEDULER_TaskContext *tc)
574 {
575   struct GNUNET_TIME_Relative next_send_time;
576   struct BloomConstructorContext bcc;
577   struct GNUNET_CONTAINER_BloomFilter *peer_bf;
578
579   find_peer_task = GNUNET_SCHEDULER_NO_TASK;
580   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
581     return;
582   if (newly_found_peers > bucket_size) 
583   {
584     /* If we are finding many peers already, no need to send out our request right now! */
585     find_peer_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
586                                                    &send_find_peer_message, NULL);
587     newly_found_peers = 0;
588     return;
589   }
590   bcc.bf_mutator = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
591   bcc.bloom =
592     GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K);
593   GNUNET_CONTAINER_multihashmap_iterate (all_known_peers, 
594                                          &add_known_to_bloom,
595                                          &bcc);
596   GNUNET_STATISTICS_update (GDS_stats,
597                             gettext_noop ("# FIND PEER messages initiated"), 1,
598                             GNUNET_NO);
599   peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
600                                                DHT_BLOOM_SIZE,
601                                                GNUNET_CONSTANTS_BLOOMFILTER_K);
602   // FIXME: pass priority!?
603   GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO,
604                              GNUNET_DHT_RO_FIND_PEER,
605                              FIND_PEER_REPLICATION_LEVEL,
606                              0,
607                              &my_identity.hashPubKey,
608                              NULL, 0,
609                              bcc.bloom, bcc.bf_mutator, 
610                              peer_bf);
611   GNUNET_CONTAINER_bloomfilter_free (peer_bf);
612   GNUNET_CONTAINER_bloomfilter_free (bcc.bloom);
613   /* schedule next round */
614   newly_found_peers = 0;
615   next_send_time.rel_value =
616     (DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value / 2) +
617     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
618                               DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value / 2);
619   find_peer_task = GNUNET_SCHEDULER_add_delayed (next_send_time, 
620                                                  &send_find_peer_message,
621                                                  NULL);  
622 }
623
624
625 /**
626  * Method called whenever a peer connects.
627  *
628  * @param cls closure
629  * @param peer peer identity this notification is about
630  * @param atsi performance data
631  */
632 static void
633 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
634                      const struct GNUNET_TRANSPORT_ATS_Information *atsi)
635 {
636   struct PeerInfo *ret;
637   int peer_bucket;
638
639   /* Check for connect to self message */
640   if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
641     return;
642   if (GNUNET_YES ==
643       GNUNET_CONTAINER_multihashmap_contains (all_known_peers,
644                                               &peer->hashPubKey))
645   {
646     GNUNET_break (0);
647     return;
648   }
649   GNUNET_STATISTICS_update (GDS_stats,
650                             gettext_noop ("# Peers connected"), 1,
651                             GNUNET_NO);
652   peer_bucket = find_bucket (&peer->hashPubKey);
653   GNUNET_assert ( (peer_bucket >= 0) && (peer_bucket < MAX_BUCKETS) );
654   ret = GNUNET_malloc (sizeof (struct PeerInfo));
655 #if 0
656   ret->latency = latency;
657   ret->distance = distance;
658 #endif
659   ret->id = *peer;
660   GNUNET_CONTAINER_DLL_insert_tail (k_buckets[peer_bucket].head,
661                                     k_buckets[peer_bucket].tail, ret);
662   k_buckets[peer_bucket].peers_size++;
663   closest_bucket = GNUNET_MAX (closest_bucket,
664                                peer_bucket);
665   if ( (peer_bucket > 0) &&
666        (k_buckets[peer_bucket].peers_size <= bucket_size) )
667     ret->preference_task = GNUNET_SCHEDULER_add_now (&update_core_preference, ret);
668   newly_found_peers++;
669   GNUNET_assert (GNUNET_OK ==
670                  GNUNET_CONTAINER_multihashmap_put (all_known_peers, 
671                                                     &peer->hashPubKey, ret,
672                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
673   if (1 == GNUNET_CONTAINER_multihashmap_size (all_known_peers))
674   {
675     /* got a first connection, good time to start with FIND PEER requests... */
676     find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
677                                                NULL);    
678   }
679 }
680
681
682 /**
683  * Method called whenever a peer disconnects.
684  *
685  * @param cls closure
686  * @param peer peer identity this notification is about
687  */
688 static void
689 handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
690 {
691   struct PeerInfo *to_remove;
692   int current_bucket;
693   struct P2PPendingMessage *pos;
694
695   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
696               "Peer `%s' disconnected!\n",
697               GNUNET_i2s (peer));
698   /* Check for disconnect from self message */
699   if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
700     return;
701   to_remove =
702       GNUNET_CONTAINER_multihashmap_get (all_known_peers, &peer->hashPubKey);
703   if (NULL == to_remove)
704     {
705       GNUNET_break (0);
706       return;
707     }
708   GNUNET_STATISTICS_update (GDS_stats,
709                             gettext_noop ("# Peers connected"), -1,
710                             GNUNET_NO);
711   GNUNET_assert (GNUNET_YES ==
712                  GNUNET_CONTAINER_multihashmap_remove (all_known_peers,
713                                                        &peer->hashPubKey,
714                                                        to_remove));
715   if (NULL != to_remove->info_ctx)
716   {
717     GNUNET_CORE_peer_change_preference_cancel (to_remove->info_ctx);
718     to_remove->info_ctx = NULL;
719   }
720   if (GNUNET_SCHEDULER_NO_TASK != to_remove->preference_task)
721   {
722     GNUNET_SCHEDULER_cancel (to_remove->preference_task);
723     to_remove->preference_task = GNUNET_SCHEDULER_NO_TASK;
724   }
725   current_bucket = find_bucket (&to_remove->id.hashPubKey);
726   GNUNET_CONTAINER_DLL_remove (k_buckets[current_bucket].head,
727                                k_buckets[current_bucket].tail,
728                                to_remove);
729   GNUNET_assert (k_buckets[current_bucket].peers_size > 0);
730   k_buckets[current_bucket].peers_size--;
731   while ( (closest_bucket > 0) &&
732           (k_buckets[closest_bucket].peers_size == 0) )
733     closest_bucket--;
734
735   if (to_remove->th != NULL) 
736   {
737     GNUNET_CORE_notify_transmit_ready_cancel (to_remove->th);
738     to_remove->th = NULL;
739   }
740   while (NULL != (pos = to_remove->head))
741   {
742     GNUNET_CONTAINER_DLL_remove (to_remove->head,
743                                  to_remove->tail,
744                                  pos);
745     GNUNET_free (pos);
746   }
747 }
748
749
750 /**
751  * Called when core is ready to send a message we asked for
752  * out to the destination.
753  *
754  * @param cls the 'struct PeerInfo' of the target peer
755  * @param size number of bytes available in buf
756  * @param buf where the callee should write the message
757  * @return number of bytes written to buf
758  */
759 static size_t
760 core_transmit_notify (void *cls, size_t size, void *buf)
761 {
762   struct PeerInfo *peer = cls;
763   char *cbuf = buf;
764   struct P2PPendingMessage *pending;
765   size_t off;
766   size_t msize;
767
768   peer->th = NULL;
769   if (buf == NULL)
770   {
771     /* client disconnected */
772     return 0;
773   }
774   if (peer->head == NULL)
775   {
776     /* no messages pending */
777     return 0;
778   }
779   off = 0;
780   while ( (NULL != (pending = peer->head)) &&
781           (size - off >= (msize = ntohs (pending->msg->size))) )
782   {
783     GNUNET_STATISTICS_update (GDS_stats,
784                               gettext_noop ("# Bytes transmitted to other peers"), msize,
785                               GNUNET_NO);
786     memcpy (&cbuf[off], pending->msg, msize);
787     off += msize;
788     peer->pending_count--;
789     GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
790     GNUNET_free (pending);
791   }
792   if (peer->head != NULL)
793     {
794       peer->th 
795         = GNUNET_CORE_notify_transmit_ready (coreAPI, GNUNET_YES,
796                                              pending->importance,
797                                              GNUNET_TIME_absolute_get_remaining (pending->timeout),
798                                              &peer->id, msize,
799                                              &core_transmit_notify, peer);
800     }
801   return off;
802 }
803
804
805 /**
806  * Transmit all messages in the peer's message queue.
807  *
808  * @param peer message queue to process
809  */
810 static void
811 process_peer_queue (struct PeerInfo *peer)
812 {
813   struct P2PPendingMessage *pending;
814
815   if (NULL == (pending = peer->head))
816     return;
817   if (NULL != peer->th)
818     return;
819   GNUNET_STATISTICS_update (GDS_stats,
820                             gettext_noop ("# Bytes of bandwdith requested from core"),
821                             ntohs (pending->msg->size),
822                             GNUNET_NO);
823   peer->th 
824     = GNUNET_CORE_notify_transmit_ready (coreAPI, GNUNET_YES,
825                                          pending->importance,
826                                          GNUNET_TIME_absolute_get_remaining (pending->timeout),
827                                          &peer->id,
828                                          ntohs (pending->msg->size),
829                                          &core_transmit_notify, peer);
830 }
831
832
833 /**
834  * To how many peers should we (on average) forward the request to
835  * obtain the desired target_replication count (on average).
836  *
837  * @param hop_count number of hops the message has traversed
838  * @param target_replication the number of total paths desired
839  * @return Some number of peers to forward the message to
840  */
841 static unsigned int
842 get_forward_count (uint32_t hop_count, 
843                    uint32_t target_replication)
844 {
845   uint32_t random_value;
846   uint32_t forward_count;
847   float target_value;
848
849   if (hop_count > GDS_NSE_get () * 4.0)
850   {
851     /* forcefully terminate */
852     return 0;
853   }
854   if (hop_count > GDS_NSE_get () * 2.0)
855   {
856     /* Once we have reached our ideal number of hops, only forward to 1 peer */
857     return 1;
858   }
859   /* bound by system-wide maximum */
860   target_replication = GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL,
861                                    target_replication);
862   target_value =
863     1 + (target_replication - 1.0) / (GDS_NSE_get () +
864                                       ((float) (target_replication - 1.0) *
865                                        hop_count));
866   /* Set forward count to floor of target_value */
867   forward_count = (uint32_t) target_value;
868   /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
869   target_value = target_value - forward_count;
870   random_value =
871     GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); 
872   if (random_value < (target_value * UINT32_MAX))
873     forward_count++;
874   return forward_count;
875 }
876
877
878 /**
879  * Compute the distance between have and target as a 32-bit value.
880  * Differences in the lower bits must count stronger than differences
881  * in the higher bits.
882  *
883  * @return 0 if have==target, otherwise a number
884  *           that is larger as the distance between
885  *           the two hash codes increases
886  */
887 static unsigned int
888 get_distance (const GNUNET_HashCode * target, const GNUNET_HashCode * have)
889 {
890   unsigned int bucket;
891   unsigned int msb;
892   unsigned int lsb;
893   unsigned int i;
894
895   /* We have to represent the distance between two 2^9 (=512)-bit
896    * numbers as a 2^5 (=32)-bit number with "0" being used for the
897    * two numbers being identical; furthermore, we need to
898    * guarantee that a difference in the number of matching
899    * bits is always represented in the result.
900    *
901    * We use 2^32/2^9 numerical values to distinguish between
902    * hash codes that have the same LSB bit distance and
903    * use the highest 2^9 bits of the result to signify the
904    * number of (mis)matching LSB bits; if we have 0 matching
905    * and hence 512 mismatching LSB bits we return -1 (since
906    * 512 itself cannot be represented with 9 bits) */
907
908   /* first, calculate the most significant 9 bits of our
909    * result, aka the number of LSBs */
910   bucket = GNUNET_CRYPTO_hash_matching_bits (target, have);
911   /* bucket is now a value between 0 and 512 */
912   if (bucket == 512)
913     return 0;                   /* perfect match */
914   if (bucket == 0)
915     return (unsigned int) -1;   /* LSB differs; use max (if we did the bit-shifting
916                                  * below, we'd end up with max+1 (overflow)) */
917
918   /* calculate the most significant bits of the final result */
919   msb = (512 - bucket) << (32 - 9);
920   /* calculate the 32-9 least significant bits of the final result by
921    * looking at the differences in the 32-9 bits following the
922    * mismatching bit at 'bucket' */
923   lsb = 0;
924   for (i = bucket + 1;
925        (i < sizeof (GNUNET_HashCode) * 8) && (i < bucket + 1 + 32 - 9); i++)
926   {
927     if (GNUNET_CRYPTO_hash_get_bit (target, i) !=
928         GNUNET_CRYPTO_hash_get_bit (have, i))
929       lsb |= (1 << (bucket + 32 - 9 - i));      /* first bit set will be 10,
930                                                  * last bit set will be 31 -- if
931                                                  * i does not reach 512 first... */
932   }
933   return msb | lsb;
934 }
935
936
937 /**
938  * Check whether my identity is closer than any known peers.  If a
939  * non-null bloomfilter is given, check if this is the closest peer
940  * that hasn't already been routed to.
941  *
942  * @param key hash code to check closeness to
943  * @param bloom bloomfilter, exclude these entries from the decision
944  * @return GNUNET_YES if node location is closest,
945  *         GNUNET_NO otherwise.
946  */
947 static int
948 am_closest_peer (const GNUNET_HashCode *key,
949                  const struct GNUNET_CONTAINER_BloomFilter *bloom)
950 {
951   int bits;
952   int other_bits;
953   int bucket_num;
954   int count;
955   struct PeerInfo *pos;
956
957   if (0 == memcmp (&my_identity.hashPubKey, key, sizeof (GNUNET_HashCode)))
958     return GNUNET_YES;
959   bucket_num = find_bucket (key);
960   bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey, key);
961   pos = k_buckets[bucket_num].head;
962   count = 0;
963   while ((pos != NULL) && (count < bucket_size))
964   {
965     if ((bloom != NULL) &&
966         (GNUNET_YES ==
967          GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)))
968     {
969       pos = pos->next;
970       continue;                 /* Skip already checked entries */
971     }
972     other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey, key);
973     if (other_bits > bits)
974       return GNUNET_NO;
975     if (other_bits == bits)        /* We match the same number of bits */
976       return GNUNET_YES;
977     pos = pos->next;
978   }
979   /* No peers closer, we are the closest! */
980   return GNUNET_YES;
981 }
982
983
984 /**
985  * Select a peer from the routing table that would be a good routing
986  * destination for sending a message for "key".  The resulting peer
987  * must not be in the set of blocked peers.<p>
988  *
989  * Note that we should not ALWAYS select the closest peer to the
990  * target, peers further away from the target should be chosen with
991  * exponentially declining probability.
992  *
993  * FIXME: double-check that this is fine
994  * 
995  *
996  * @param key the key we are selecting a peer to route to
997  * @param bloom a bloomfilter containing entries this request has seen already
998  * @param hops how many hops has this message traversed thus far
999  * @return Peer to route to, or NULL on error
1000  */
1001 static struct PeerInfo *
1002 select_peer (const GNUNET_HashCode *key,
1003              const struct GNUNET_CONTAINER_BloomFilter *bloom, 
1004              uint32_t hops)
1005 {
1006   unsigned int bc;
1007   unsigned int count;
1008   unsigned int selected;
1009   struct PeerInfo *pos;
1010   unsigned int dist;
1011   unsigned int smallest_distance;
1012   struct PeerInfo *chosen;
1013
1014   if (hops >= GDS_NSE_get ())
1015   {
1016     /* greedy selection (closest peer that is not in bloomfilter) */
1017     smallest_distance = UINT_MAX;
1018     chosen = NULL;
1019     for (bc = closest_bucket; bc < MAX_BUCKETS; bc++)
1020     {
1021       pos = k_buckets[bc].head;
1022       count = 0;
1023       while ((pos != NULL) && (count < bucket_size))
1024       {
1025         if (GNUNET_NO ==
1026             GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
1027         {
1028           dist = get_distance (key, &pos->id.hashPubKey);
1029           if (dist < smallest_distance)
1030           {
1031             chosen = pos;
1032             smallest_distance = dist;
1033           }
1034         }
1035         else
1036         {
1037           GNUNET_STATISTICS_update (GDS_stats,
1038                                     gettext_noop ("# Peers excluded from routing due to Bloomfilter"), 1,
1039                                     GNUNET_NO);
1040         }
1041         count++;
1042         pos = pos->next;
1043       }
1044     }
1045     if (NULL == chosen)
1046       GNUNET_STATISTICS_update (GDS_stats,
1047                                 gettext_noop ("# Peer selection failed"), 1,
1048                                 GNUNET_NO);
1049     return chosen;
1050   }
1051
1052   /* select "random" peer */
1053   /* count number of peers that are available and not filtered */
1054   count = 0;
1055   for (bc = closest_bucket; bc < MAX_BUCKETS; bc++)
1056   {
1057     pos = k_buckets[bc].head;
1058     while ((pos != NULL) && (count < bucket_size))
1059     {
1060       if ( (bloom != NULL) &&
1061            (GNUNET_YES ==
1062             GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) )
1063       {
1064         GNUNET_STATISTICS_update (GDS_stats,
1065                                   gettext_noop ("# Peers excluded from routing due to Bloomfilter"), 1,
1066                                   GNUNET_NO);
1067         pos = pos->next;
1068         continue;               /* Ignore bloomfiltered peers */
1069       }
1070       count++;
1071       pos = pos->next;
1072     }
1073   }
1074   if (count == 0)               /* No peers to select from! */
1075   {
1076     GNUNET_STATISTICS_update (GDS_stats,
1077                               gettext_noop ("# Peer selection failed"), 1,
1078                               GNUNET_NO);
1079     return NULL;
1080   }
1081   /* Now actually choose a peer */
1082   selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, count);
1083   count = 0;
1084   for (bc = closest_bucket; bc < MAX_BUCKETS; bc++)
1085   {
1086     pos = k_buckets[bc].head;
1087     while ((pos != NULL) && (count < bucket_size))
1088     {
1089       if ( (bloom != NULL) &&
1090            (GNUNET_YES ==
1091             GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)) )
1092       {
1093         pos = pos->next;
1094         continue;               /* Ignore bloomfiltered peers */
1095       }
1096       if (0 == selected--)
1097         return pos;
1098       pos = pos->next;
1099     }
1100   }
1101   GNUNET_break (0);
1102   return NULL;
1103 }
1104
1105
1106 /**
1107  * Compute the set of peers that the given request should be
1108  * forwarded to.
1109  *
1110  * @param key routing key
1111  * @param bloom bloom filter excluding peers as targets, all selected
1112  *        peers will be added to the bloom filter
1113  * @param hop_count number of hops the request has traversed so far
1114  * @param target_replication desired number of replicas
1115  * @param targets where to store an array of target peers (to be
1116  *         free'd by the caller)
1117  * @return number of peers returned in 'targets'.
1118  */
1119 static unsigned int
1120 get_target_peers (const GNUNET_HashCode *key,
1121                   struct GNUNET_CONTAINER_BloomFilter *bloom,
1122                   uint32_t hop_count,
1123                   uint32_t target_replication,
1124                   struct PeerInfo ***targets)
1125 {
1126   unsigned int ret;
1127   unsigned int off;
1128   struct PeerInfo **rtargets;
1129   struct PeerInfo *nxt;
1130
1131   GNUNET_assert (NULL != bloom);
1132   ret = get_forward_count (hop_count, target_replication);
1133   if (ret == 0)
1134   {
1135     *targets = NULL;
1136     return 0;
1137   }
1138   rtargets = GNUNET_malloc (sizeof (struct PeerInfo*) * ret);
1139   off = 0;
1140   while (ret-- > 0)
1141   {
1142     nxt = select_peer (key, bloom, hop_count);
1143     if (nxt == NULL)
1144       break;      
1145     rtargets[off++] = nxt;
1146     GNUNET_break (GNUNET_NO ==
1147                   GNUNET_CONTAINER_bloomfilter_test (bloom, &nxt->id.hashPubKey));
1148     GNUNET_CONTAINER_bloomfilter_add (bloom, &nxt->id.hashPubKey);
1149   }
1150   if (0 == off)
1151   {
1152     GNUNET_free (rtargets);
1153     *targets = NULL;
1154     return 0;
1155   }
1156   *targets = rtargets;
1157   return off;
1158 }
1159
1160
1161 /**
1162  * Perform a PUT operation.   Forwards the given request to other
1163  * peers.   Does not store the data locally.  Does not give the
1164  * data to local clients.  May do nothing if this is the only
1165  * peer in the network (or if we are the closest peer in the
1166  * network).
1167  *
1168  * @param type type of the block
1169  * @param options routing options
1170  * @param desired_replication_level desired replication count
1171  * @param expiration_time when does the content expire
1172  * @param hop_count how many hops has this message traversed so far
1173  * @param bf Bloom filter of peers this PUT has already traversed
1174  * @param key key for the content
1175  * @param put_path_length number of entries in put_path
1176  * @param put_path peers this request has traversed so far (if tracked)
1177  * @param data payload to store
1178  * @param data_size number of bytes in data
1179  */
1180 void
1181 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1182                            enum GNUNET_DHT_RouteOption options,
1183                            uint32_t desired_replication_level,
1184                            struct GNUNET_TIME_Absolute expiration_time,
1185                            uint32_t hop_count,
1186                            struct GNUNET_CONTAINER_BloomFilter *bf,
1187                            const GNUNET_HashCode *key,
1188                            unsigned int put_path_length,
1189                            struct GNUNET_PeerIdentity *put_path,
1190                            const void *data,
1191                            size_t data_size)
1192 {
1193   unsigned int target_count;
1194   unsigned int i;
1195   struct PeerInfo **targets;
1196   struct PeerInfo *target;
1197   struct P2PPendingMessage *pending;
1198   size_t msize;
1199   struct PeerPutMessage *ppm;
1200   struct GNUNET_PeerIdentity *pp;
1201   
1202   GNUNET_assert (NULL != bf);
1203   GNUNET_CONTAINER_bloomfilter_add (bf, &my_identity.hashPubKey);
1204   GNUNET_STATISTICS_update (GDS_stats,
1205                             gettext_noop ("# PUT requests routed"), 1,
1206                             GNUNET_NO);
1207   target_count = get_target_peers (key, bf, hop_count,
1208                                    desired_replication_level,
1209                                    &targets);
1210   if (0 == target_count)
1211     return;
1212   msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + sizeof (struct PeerPutMessage);
1213   if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1214   {
1215     put_path_length = 0;
1216     msize = data_size + sizeof (struct PeerPutMessage);
1217   }
1218   if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1219   {
1220     GNUNET_break (0);
1221     return;
1222   }
1223   GNUNET_STATISTICS_update (GDS_stats,
1224                             gettext_noop ("# Peers selected as targets for PUT requests"), target_count,
1225                             GNUNET_NO);
1226   for (i=0;i<target_count;i++)
1227   {
1228     target = targets[i];
1229     pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1230     pending->importance = 0; /* FIXME */
1231     pending->timeout = expiration_time;   
1232     ppm = (struct PeerPutMessage*) &pending[1];
1233     pending->msg = &ppm->header;
1234     ppm->header.size = htons (msize);
1235     ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1236     ppm->options = htonl (options);
1237     ppm->type = htonl (type);
1238     ppm->hop_count = htonl (hop_count + 1);
1239     ppm->desired_replication_level = htonl (desired_replication_level);
1240     ppm->put_path_length = htonl (put_path_length);
1241     ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1242     GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &target->id.hashPubKey));
1243     GNUNET_assert (GNUNET_OK ==
1244                    GNUNET_CONTAINER_bloomfilter_get_raw_data (bf,
1245                                                               ppm->bloomfilter,
1246                                                               DHT_BLOOM_SIZE));
1247     ppm->key = *key;
1248     pp = (struct GNUNET_PeerIdentity*) &ppm[1];
1249     memcpy (pp, put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length);
1250     memcpy (&pp[put_path_length], data, data_size);
1251     GNUNET_CONTAINER_DLL_insert_tail (target->head,
1252                                       target->tail,
1253                                       pending);
1254     target->pending_count++;
1255     process_peer_queue (target);
1256   }
1257   GNUNET_free (targets);
1258 }
1259
1260
1261 /**
1262  * Perform a GET operation.  Forwards the given request to other
1263  * peers.  Does not lookup the key locally.  May do nothing if this is
1264  * the only peer in the network (or if we are the closest peer in the
1265  * network).
1266  *
1267  * @param type type of the block
1268  * @param options routing options
1269  * @param desired_replication_level desired replication count
1270  * @param hop_count how many hops did this request traverse so far?
1271  * @param key key for the content
1272  * @param xquery extended query
1273  * @param xquery_size number of bytes in xquery
1274  * @param reply_bf bloomfilter to filter duplicates
1275  * @param reply_bf_mutator mutator for reply_bf
1276  * @param peer_bf filter for peers not to select (again)
1277  */
1278 void
1279 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1280                            enum GNUNET_DHT_RouteOption options,
1281                            uint32_t desired_replication_level,
1282                            uint32_t hop_count,
1283                            const GNUNET_HashCode *key,
1284                            const void *xquery,
1285                            size_t xquery_size,
1286                            const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
1287                            uint32_t reply_bf_mutator,
1288                            struct GNUNET_CONTAINER_BloomFilter *peer_bf)
1289 {
1290   unsigned int target_count;
1291   unsigned int i;
1292   struct PeerInfo **targets;
1293   struct PeerInfo *target;
1294   struct P2PPendingMessage *pending;
1295   size_t msize;
1296   struct PeerGetMessage *pgm;
1297   char *xq;
1298   size_t reply_bf_size;
1299
1300   GNUNET_assert (NULL != peer_bf);  
1301   GNUNET_CONTAINER_bloomfilter_add (peer_bf, &my_identity.hashPubKey);
1302   GNUNET_STATISTICS_update (GDS_stats,
1303                             gettext_noop ("# GET requests routed"), 1,
1304                             GNUNET_NO);
1305   target_count = get_target_peers (key, peer_bf, hop_count,
1306                                    desired_replication_level,
1307                                    &targets);
1308   if (0 == target_count)
1309     return;
1310   reply_bf_size = GNUNET_CONTAINER_bloomfilter_get_size (reply_bf);
1311   msize = xquery_size + sizeof (struct PeerGetMessage) + reply_bf_size;
1312   if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1313   {
1314     GNUNET_break (0);
1315     return;
1316   }
1317   GNUNET_STATISTICS_update (GDS_stats,
1318                             gettext_noop ("# Peers selected as targets for GET requests"), target_count,
1319                             GNUNET_NO);
1320   /* forward request */
1321   for (i=0;i<target_count;i++)
1322   {
1323     target = targets[i];
1324     pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); 
1325     pending->importance = 0; /* FIXME */
1326     pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT);
1327     pgm = (struct PeerGetMessage*) &pending[1];
1328     pending->msg = &pgm->header;
1329     pgm->header.size = htons (msize);
1330     pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
1331     pgm->options = htonl (options);
1332     pgm->type = htonl (type);
1333     pgm->hop_count = htonl (hop_count + 1);
1334     pgm->desired_replication_level = htonl (desired_replication_level);
1335     pgm->xquery_size = htonl (xquery_size);
1336     pgm->bf_mutator = reply_bf_mutator; 
1337     GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (peer_bf, &target->id.hashPubKey));
1338     GNUNET_assert (GNUNET_OK ==
1339                    GNUNET_CONTAINER_bloomfilter_get_raw_data (peer_bf,
1340                                                               pgm->bloomfilter,
1341                                                               DHT_BLOOM_SIZE));
1342     pgm->key = *key;
1343     xq = (char *) &pgm[1];
1344     memcpy (xq, xquery, xquery_size);
1345     if (NULL != reply_bf)
1346       GNUNET_assert (GNUNET_OK ==
1347                      GNUNET_CONTAINER_bloomfilter_get_raw_data (reply_bf,
1348                                                                 &xq[xquery_size],
1349                                                                 reply_bf_size));
1350     GNUNET_CONTAINER_DLL_insert_tail (target->head,
1351                                       target->tail,
1352                                       pending);
1353     target->pending_count++;
1354     process_peer_queue (target);
1355   }
1356   GNUNET_free (targets);
1357 }
1358
1359
1360 /**
1361  * Handle a reply (route to origin).  Only forwards the reply back to
1362  * the given peer.  Does not do local caching or forwarding to local
1363  * clients.
1364  *
1365  * @param target neighbour that should receive the block (if still connected)
1366  * @param type type of the block
1367  * @param expiration_time when does the content expire
1368  * @param key key for the content
1369  * @param put_path_length number of entries in put_path
1370  * @param put_path peers the original PUT traversed (if tracked)
1371  * @param get_path_length number of entries in put_path
1372  * @param get_path peers this reply has traversed so far (if tracked)
1373  * @param data payload of the reply
1374  * @param data_size number of bytes in data
1375  */
1376 void
1377 GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
1378                              enum GNUNET_BLOCK_Type type,
1379                              struct GNUNET_TIME_Absolute expiration_time,
1380                              const GNUNET_HashCode *key,
1381                              unsigned int put_path_length,
1382                              const struct GNUNET_PeerIdentity *put_path,
1383                              unsigned int get_path_length,
1384                              const struct GNUNET_PeerIdentity *get_path,
1385                              const void *data,
1386                              size_t data_size)
1387 {
1388   struct PeerInfo *pi;
1389   struct P2PPendingMessage *pending;
1390   size_t msize;
1391   struct PeerResultMessage *prm;
1392   struct GNUNET_PeerIdentity *paths;
1393   
1394   msize = data_size + sizeof (struct PeerResultMessage) + 
1395     (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
1396   if ( (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1397        (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1398        (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1399        (data_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) )
1400   {
1401     GNUNET_break (0);
1402     return;
1403   }
1404   pi = GNUNET_CONTAINER_multihashmap_get (all_known_peers,
1405                                           &target->hashPubKey);
1406   if (NULL == pi)
1407   {
1408     /* peer disconnected in the meantime, drop reply */
1409     return;
1410   }
1411   GNUNET_STATISTICS_update (GDS_stats,
1412                             gettext_noop ("# REPLIES routed"), 1,
1413                             GNUNET_NO);
1414   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); 
1415   pending->importance = 0; /* FIXME */
1416   pending->timeout = expiration_time;
1417   prm = (struct PeerResultMessage*) &pending[1];
1418   pending->msg = &prm->header;
1419   prm->header.size = htons (msize);
1420   prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1421   prm->type = htonl (type);
1422   prm->put_path_length = htonl (put_path_length);
1423   prm->get_path_length = htonl (get_path_length);
1424   prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
1425   prm->key = *key;
1426   paths = (struct GNUNET_PeerIdentity*) &prm[1];
1427   memcpy (paths, put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity));
1428   memcpy (&paths[put_path_length],
1429           get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
1430   memcpy (&paths[put_path_length + get_path_length],
1431           data, data_size);
1432   GNUNET_CONTAINER_DLL_insert (pi->head,
1433                                pi->tail,
1434                                pending);
1435   pi->pending_count++;
1436   process_peer_queue (pi);
1437 }
1438
1439
1440 /**
1441  * To be called on core init/fail.
1442  *
1443  * @param cls service closure
1444  * @param server handle to the server for this service
1445  * @param identity the public identity of this peer
1446  * @param publicKey the public key of this peer
1447  */
1448 static void
1449 core_init (void *cls, struct GNUNET_CORE_Handle *server,
1450            const struct GNUNET_PeerIdentity *identity,
1451            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1452 {
1453   GNUNET_assert (server != NULL);
1454   my_identity = *identity;
1455 }
1456
1457
1458 /**
1459  * Core handler for p2p put requests.
1460  *
1461  * @param cls closure
1462  * @param peer sender of the request
1463  * @param message message
1464  * @param peer peer identity this notification is about
1465  * @param atsi performance data
1466  * @return GNUNET_OK to keep the connection open,
1467  *         GNUNET_SYSERR to close it (signal serious error)
1468  */
1469 static int
1470 handle_dht_p2p_put (void *cls,
1471                     const struct GNUNET_PeerIdentity *peer,
1472                     const struct GNUNET_MessageHeader *message,
1473                     const struct GNUNET_TRANSPORT_ATS_Information
1474                     *atsi)
1475 {
1476   const struct PeerPutMessage *put;
1477   const struct GNUNET_PeerIdentity *put_path;
1478   const void *payload;
1479   uint32_t putlen;
1480   uint16_t msize;
1481   size_t payload_size;
1482   enum GNUNET_DHT_RouteOption options;
1483   struct GNUNET_CONTAINER_BloomFilter *bf;
1484   GNUNET_HashCode test_key;
1485   
1486   msize = ntohs (message->size);
1487   if (msize < sizeof (struct PeerPutMessage))
1488   {
1489     GNUNET_break_op (0);
1490     return GNUNET_YES;
1491   }
1492   put = (const struct PeerPutMessage*) message;
1493   putlen = ntohl (put->put_path_length);
1494   if ( (msize < sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)) ||
1495        (putlen > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) )
1496     {
1497       GNUNET_break_op (0);
1498       return GNUNET_YES;
1499     }
1500   GNUNET_STATISTICS_update (GDS_stats,
1501                             gettext_noop ("# P2P PUT requests received"), 1,
1502                             GNUNET_NO);
1503   put_path = (const struct GNUNET_PeerIdentity*) &put[1];  
1504   payload = &put_path[putlen];
1505   options = ntohl (put->options);
1506   payload_size = msize - (sizeof (struct PeerPutMessage) + 
1507                           putlen * sizeof (struct GNUNET_PeerIdentity));
1508   switch (GNUNET_BLOCK_get_key (GDS_block_context,
1509                                 ntohl (put->type),
1510                                 payload, payload_size,
1511                                 &test_key))
1512   {
1513   case GNUNET_YES:
1514     if (0 != memcmp (&test_key, &put->key, sizeof (GNUNET_HashCode)))
1515     {
1516       GNUNET_break_op (0);
1517       return GNUNET_YES;
1518     }
1519     break;
1520   case GNUNET_NO:
1521     GNUNET_break_op (0);
1522     return GNUNET_YES;
1523   case GNUNET_SYSERR:
1524     /* cannot verify, good luck */
1525     break;
1526   }
1527   bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
1528                                           DHT_BLOOM_SIZE,
1529                                           GNUNET_CONSTANTS_BLOOMFILTER_K);
1530   GNUNET_break_op (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &peer->hashPubKey));
1531   {
1532     struct GNUNET_PeerIdentity pp[putlen+1];
1533   
1534     /* extend 'put path' by sender */
1535     if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1536     {
1537       memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
1538       pp[putlen] = *peer;
1539       putlen++;
1540     }
1541     else
1542       putlen = 0;
1543     
1544     /* give to local clients */
1545     GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (put->expiration_time),
1546                              &put->key,
1547                              0, NULL,
1548                              putlen,
1549                              pp,
1550                              ntohl (put->type),
1551                              payload_size,
1552                              payload);
1553     /* store locally */
1554     if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1555          (am_closest_peer (&put->key,
1556                            bf) ) )
1557       GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
1558                                 &put->key,
1559                                 putlen, pp,
1560                                 ntohl (put->type),
1561                                 payload_size,
1562                                 payload);
1563     /* route to other peers */
1564     GDS_NEIGHBOURS_handle_put (ntohl (put->type),
1565                                options,
1566                                ntohl (put->desired_replication_level),
1567                                GNUNET_TIME_absolute_ntoh (put->expiration_time),
1568                                ntohl (put->hop_count) + 1 /* who adds +1? */,
1569                                bf,
1570                                &put->key,
1571                                putlen, pp,
1572                                payload,
1573                                payload_size);
1574   }
1575   GNUNET_CONTAINER_bloomfilter_free (bf);
1576   return GNUNET_YES;
1577 }
1578
1579
1580 /**
1581  * We have received a FIND PEER request.  Send matching
1582  * HELLOs back.
1583  *
1584  * @param sender sender of the FIND PEER request
1585  * @param key peers close to this key are desired
1586  * @param bf peers matching this bf are excluded
1587  * @param bf_mutator mutator for bf
1588  */
1589 static void
1590 handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1591                   const GNUNET_HashCode *key,
1592                   struct GNUNET_CONTAINER_BloomFilter *bf,
1593                   uint32_t bf_mutator)
1594 {
1595   int bucket_idx;
1596   struct PeerBucket *bucket;
1597   struct PeerInfo *peer;
1598   unsigned int choice;
1599   GNUNET_HashCode mhash;
1600   const struct GNUNET_HELLO_Message *hello;
1601
1602   /* first, check about our own HELLO */
1603   if (NULL != GDS_my_hello)
1604   {
1605     GNUNET_BLOCK_mingle_hash (&my_identity.hashPubKey, bf_mutator, &mhash);
1606     if ( (NULL == bf) ||
1607          (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)) )
1608     {
1609       GDS_NEIGHBOURS_handle_reply (sender,
1610                                    GNUNET_BLOCK_TYPE_DHT_HELLO,
1611                                    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION),
1612                                    key,
1613                                    0, NULL,
1614                                    0, NULL,
1615                                    GDS_my_hello,
1616                                    GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message*) GDS_my_hello));
1617     }
1618     else
1619     {
1620       GNUNET_STATISTICS_update (GDS_stats,
1621                                 gettext_noop ("# FIND PEER requests ignored due to Bloomfilter"), 1,
1622                                 GNUNET_NO);
1623     }
1624   }
1625   else
1626   {
1627     GNUNET_STATISTICS_update (GDS_stats,
1628                               gettext_noop ("# FIND PEER requests ignored due to lack of HELLO"), 1,
1629                               GNUNET_NO);
1630   }
1631
1632   /* then, also consider sending a random HELLO from the closest bucket */
1633   if (0 == memcmp (&my_identity.hashPubKey, key, sizeof (GNUNET_HashCode)))
1634     bucket_idx = closest_bucket;
1635   else
1636     bucket_idx = GNUNET_MIN (closest_bucket, find_bucket (key));
1637   if (bucket_idx == GNUNET_SYSERR)
1638     return;
1639   bucket = &k_buckets[bucket_idx];
1640   if (bucket->peers_size == 0)
1641     return;
1642   choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1643                                      bucket->peers_size);
1644   peer = bucket->head;
1645   while (choice > 0)
1646   {
1647     GNUNET_assert (peer != NULL);
1648     peer = peer->next;
1649   }
1650   choice = bucket->peers_size;
1651   do
1652     {
1653       peer = peer->next;
1654       if (choice-- == 0)
1655         return; /* no non-masked peer available */
1656       if (peer == NULL)
1657         peer = bucket->head;
1658       GNUNET_BLOCK_mingle_hash (&peer->id.hashPubKey, bf_mutator, &mhash);
1659       hello = GDS_HELLO_get (&peer->id);
1660     }
1661   while ( (hello == NULL) ||
1662           (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)) );
1663   GDS_NEIGHBOURS_handle_reply (sender,
1664                                GNUNET_BLOCK_TYPE_DHT_HELLO,
1665                                GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION),
1666                                key,
1667                                0, NULL,
1668                                0, NULL,
1669                                hello,
1670                                GNUNET_HELLO_size (hello));    
1671 }
1672
1673
1674 /**
1675  * Core handler for p2p get requests.
1676  *
1677  * @param cls closure
1678  * @param peer sender of the request
1679  * @param message message
1680  * @param peer peer identity this notification is about
1681  * @param atsi performance data
1682  * @return GNUNET_OK to keep the connection open,
1683  *         GNUNET_SYSERR to close it (signal serious error)
1684  */
1685 static int
1686 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
1687                     const struct GNUNET_MessageHeader *message,
1688                     const struct GNUNET_TRANSPORT_ATS_Information
1689                     *atsi)
1690 {
1691   struct PeerGetMessage *get;
1692   uint32_t xquery_size;
1693   size_t reply_bf_size;
1694   uint16_t msize;
1695   enum GNUNET_BLOCK_Type type;
1696   enum GNUNET_DHT_RouteOption options;
1697   enum GNUNET_BLOCK_EvaluationResult eval;
1698   struct GNUNET_CONTAINER_BloomFilter *reply_bf;
1699   struct GNUNET_CONTAINER_BloomFilter *peer_bf;
1700   const char *xquery;
1701
1702   GNUNET_break (0 != memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)));
1703   /* parse and validate message */
1704   msize = ntohs (message->size);
1705   if (msize < sizeof (struct PeerGetMessage))
1706   {
1707     GNUNET_break_op (0);
1708     return GNUNET_YES;
1709   }
1710   get = (struct PeerGetMessage *) message;
1711   xquery_size = ntohl (get->xquery_size);
1712   if (msize < sizeof (struct PeerGetMessage) + xquery_size)
1713   {
1714     GNUNET_break_op (0);
1715     return GNUNET_YES;
1716   }
1717   GNUNET_STATISTICS_update (GDS_stats,
1718                             gettext_noop ("# P2P GET requests received"), 1,
1719                             GNUNET_NO);
1720   reply_bf_size = msize - (sizeof (struct PeerGetMessage) + xquery_size);
1721   type = ntohl (get->type);
1722   options = ntohl (get->options);
1723   xquery = (const char*) &get[1];
1724   reply_bf = NULL;
1725   if (reply_bf_size > 0)
1726     reply_bf = GNUNET_CONTAINER_bloomfilter_init (&xquery[xquery_size],
1727                                                   reply_bf_size,
1728                                                   GNUNET_CONSTANTS_BLOOMFILTER_K);
1729   eval = GNUNET_BLOCK_evaluate (GDS_block_context,
1730                                 type,
1731                                 &get->key,
1732                                 &reply_bf,
1733                                 get->bf_mutator,
1734                                 xquery, xquery_size,
1735                                 NULL, 0);
1736   if (eval != GNUNET_BLOCK_EVALUATION_REQUEST_VALID)
1737   {
1738     /* request invalid or block type not supported */
1739     GNUNET_break_op (eval == GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED);
1740     if (NULL != reply_bf)
1741       GNUNET_CONTAINER_bloomfilter_free (reply_bf);
1742     return GNUNET_YES;
1743   }
1744   peer_bf =
1745     GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter, 
1746                                        DHT_BLOOM_SIZE,
1747                                        GNUNET_CONSTANTS_BLOOMFILTER_K);
1748   GNUNET_break_op (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (peer_bf, &peer->hashPubKey));
1749   /* remember request for routing replies */
1750   GDS_ROUTING_add (peer,
1751                    type,
1752                    options,
1753                    &get->key,
1754                    xquery, xquery_size,
1755                    reply_bf, get->bf_mutator);
1756
1757   /* local lookup (this may update the reply_bf) */
1758   if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1759        (am_closest_peer (&get->key,
1760                          peer_bf) ) )
1761   {
1762     if ( (0 != (options & GNUNET_DHT_RO_FIND_PEER)))
1763     {
1764       GNUNET_STATISTICS_update (GDS_stats,
1765                                 gettext_noop ("# P2P FIND PEER requests processed"), 1,
1766                                 GNUNET_NO);
1767       handle_find_peer (peer,
1768                         &get->key,
1769                         reply_bf,
1770                         get->bf_mutator);
1771     }
1772     else
1773     {
1774       eval = GDS_DATACACHE_handle_get (&get->key,
1775                                        type,
1776                                        xquery, xquery_size,
1777                                        &reply_bf, 
1778                                        get->bf_mutator);
1779     }
1780   }
1781   else
1782   {
1783     GNUNET_STATISTICS_update (GDS_stats,
1784                               gettext_noop ("# P2P GET requests ONLY routed"), 1,
1785                               GNUNET_NO);
1786   }
1787   
1788   /* P2P forwarding */
1789   if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
1790     GDS_NEIGHBOURS_handle_get (type,
1791                                options,
1792                                ntohl (get->desired_replication_level),
1793                                ntohl (get->hop_count) + 1, /* CHECK: where (else) do we do +1? */
1794                                &get->key,
1795                                xquery, xquery_size,
1796                                reply_bf,
1797                                get->bf_mutator,
1798                                peer_bf);
1799   /* clean up */
1800   if (NULL != reply_bf)
1801     GNUNET_CONTAINER_bloomfilter_free (reply_bf);
1802   GNUNET_CONTAINER_bloomfilter_free (peer_bf);  
1803   return GNUNET_YES;
1804 }
1805
1806
1807 /**
1808  * Core handler for p2p result messages.
1809  *
1810  * @param cls closure
1811  * @param message message
1812  * @param peer peer identity this notification is about
1813  * @param atsi performance data
1814  * @return GNUNET_YES (do not cut p2p connection)
1815  */
1816 static int
1817 handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer,
1818                        const struct GNUNET_MessageHeader *message,
1819                        const struct GNUNET_TRANSPORT_ATS_Information
1820                        *atsi)
1821 {
1822   const struct PeerResultMessage *prm;
1823   const struct GNUNET_PeerIdentity *put_path;
1824   const struct GNUNET_PeerIdentity *get_path;
1825   const void *data;
1826   uint32_t get_path_length;
1827   uint32_t put_path_length;
1828   uint16_t msize;
1829   size_t data_size;
1830   enum GNUNET_BLOCK_Type type;
1831                        
1832   /* parse and validate message */
1833   msize = ntohs (message->size);
1834   if (msize < sizeof (struct PeerResultMessage))
1835   {
1836     GNUNET_break_op (0);
1837     return GNUNET_YES;
1838   }
1839   prm = (struct PeerResultMessage *) message;
1840   put_path_length = ntohl (prm->put_path_length);
1841   get_path_length = ntohl (prm->get_path_length);
1842   if ( (msize < sizeof (struct PeerResultMessage) + 
1843         (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)) ||
1844        (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
1845        (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) )
1846   {
1847     GNUNET_break_op (0);
1848     return GNUNET_YES;
1849   } 
1850   GNUNET_STATISTICS_update (GDS_stats,
1851                             gettext_noop ("# P2P RESULTS received"), 1,
1852                             GNUNET_NO);
1853   put_path = (const struct GNUNET_PeerIdentity*) &prm[1];
1854   get_path = &put_path[put_path_length];
1855   type = ntohl (prm->type);
1856   data = (const void*) &get_path[get_path_length];
1857   data_size = msize - (sizeof (struct PeerResultMessage) + 
1858                        (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity));
1859
1860   /* if we got a HELLO, consider it for our own routing table */
1861   if (type == GNUNET_BLOCK_TYPE_DHT_HELLO)
1862   {
1863     const struct GNUNET_MessageHeader *h;
1864     struct GNUNET_PeerIdentity pid;
1865     int bucket;
1866
1867     /* Should be a HELLO, validate and consider using it! */
1868     if (data_size < sizeof (struct GNUNET_MessageHeader))
1869     {
1870       GNUNET_break_op (0);
1871       return GNUNET_YES;
1872     }
1873     h = data;
1874     if (data_size != ntohs (h->size))
1875     {
1876       GNUNET_break_op (0);
1877       return GNUNET_YES;
1878     }
1879     if (GNUNET_OK !=
1880         GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message*) h,
1881                              &pid))
1882     {
1883       GNUNET_break_op (0);
1884       return GNUNET_YES;
1885     }
1886     if (0 != memcmp (&my_identity, &pid, sizeof (struct GNUNET_PeerIdentity)))
1887     {
1888       bucket = find_bucket (&pid.hashPubKey);
1889       if ( (bucket >= 0) &&
1890            (k_buckets[bucket].peers_size < bucket_size) )
1891         {    
1892           if (NULL != GDS_transport_handle)
1893             GNUNET_TRANSPORT_offer_hello (GDS_transport_handle,
1894                                           h, NULL, NULL);
1895           (void) GNUNET_CORE_peer_request_connect (coreAPI,
1896                                                    &pid, 
1897                                                    NULL, NULL);
1898         }   
1899     }
1900   }
1901
1902   /* append 'peer' to 'get_path' */
1903   {    
1904     struct GNUNET_PeerIdentity xget_path[get_path_length+1];
1905
1906     memcpy (xget_path, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
1907     xget_path[get_path_length] = *peer;
1908     get_path_length++;
1909
1910     /* forward to local clients */   
1911     GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (prm->expiration_time),
1912                              &prm->key,
1913                              get_path_length,
1914                              xget_path,
1915                              put_path_length,
1916                              put_path,
1917                              type,
1918                              data_size, 
1919                              data);
1920
1921     /* forward to other peers */
1922     GDS_ROUTING_process (type,
1923                          GNUNET_TIME_absolute_ntoh (prm->expiration_time),
1924                          &prm->key,
1925                          put_path_length,
1926                          put_path,
1927                          get_path_length,
1928                          xget_path,
1929                          data,
1930                          data_size);                     
1931   }
1932   return GNUNET_YES;
1933 }
1934
1935
1936 /**
1937  * Initialize neighbours subsystem.
1938  *
1939  * @return GNUNET_OK on success, GNUNET_SYSERR on error
1940  */
1941 int
1942 GDS_NEIGHBOURS_init ()
1943 {
1944   static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1945     {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
1946     {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
1947     {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0},
1948     {NULL, 0, 0}
1949   };
1950   unsigned long long temp_config_num;
1951  
1952   if (GNUNET_OK ==
1953       GNUNET_CONFIGURATION_get_value_number (GDS_cfg, "DHT", "bucket_size",
1954                                              &temp_config_num))
1955     bucket_size = (unsigned int) temp_config_num;  
1956   coreAPI = GNUNET_CORE_connect (GDS_cfg,
1957                                  1,
1958                                  NULL,
1959                                  &core_init,
1960                                  &handle_core_connect,
1961                                  &handle_core_disconnect, 
1962                                  NULL,  /* Do we care about "status" updates? */
1963                                  NULL, GNUNET_NO,
1964                                  NULL, GNUNET_NO,
1965                                  core_handlers);
1966   if (coreAPI == NULL)
1967     return GNUNET_SYSERR;
1968   all_known_peers = GNUNET_CONTAINER_multihashmap_create (256);
1969   return GNUNET_OK;
1970 }
1971
1972
1973 /**
1974  * Shutdown neighbours subsystem.
1975  */
1976 void
1977 GDS_NEIGHBOURS_done ()
1978 {
1979   if (coreAPI == NULL)
1980     return;
1981   GNUNET_CORE_disconnect (coreAPI);
1982   coreAPI = NULL;    
1983   GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (all_known_peers));
1984   GNUNET_CONTAINER_multihashmap_destroy (all_known_peers);
1985   all_known_peers = NULL;
1986   if (GNUNET_SCHEDULER_NO_TASK != find_peer_task)
1987   {
1988     GNUNET_SCHEDULER_cancel (find_peer_task);
1989     find_peer_task = GNUNET_SCHEDULER_NO_TASK;
1990   }
1991 }
1992
1993
1994 /* end of gnunet-service-dht_neighbours.c */