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