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