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