starting with whanu
[oweals/gnunet.git] / src / dht / gnunet-service-wdht_neighbours.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2014 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-xdht_neighbours.c
23  * @brief GNUnet DHT service's finger and friend table management code
24  * @author Supriti Singh
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_block_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_ats_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_datacache_lib.h"
36 #include "gnunet_transport_service.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet-service-xdht.h"
40 #include "gnunet-service-wdht_clients.h"
41 #include "gnunet-service-wdht_datacache.h"
42 #include "gnunet-service-wdht_neighbours.h"
43 #include "gnunet-service-wdht_routing.h"
44 #include <fenv.h>
45 #include "dht.h"
46
47 #define DEBUG(...)                                           \
48   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
49
50 /**
51  * FIXME
52  */
53 #define FOO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
54
55
56 GNUNET_NETWORK_STRUCT_BEGIN
57
58 /**
59  * Setup a finger using the underlay topology ("social network").
60  */
61 struct FingerSetupMessage
62 {
63   /**
64    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP
65    */
66   struct GNUNET_MessageHeader header;
67
68   /**
69    * Number of hops this message has taken so far, we stop at
70    * log(NSE), in NBO.
71    */
72   uint16_t hops_taken GNUNET_PACKED;
73
74   /**
75    * Layer for the request, in NBO.
76    */
77   uint16_t layer GNUNET_PACKED;
78
79   /**
80    * Unique (random) identifier this peer will use to
81    * identify the finger (in future messages).
82    */
83   struct GNUNET_HashCode finger_id;
84
85 };
86
87
88 /**
89  * Response to a `struct FingerSetupMessage`.
90  */
91 struct FingerSetupResponseMessage
92 {
93   /**
94    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP_RESPONSE
95    */
96   struct GNUNET_MessageHeader header;
97
98   /**
99    * Zero, for alignment.
100    */
101   uint32_t reserved GNUNET_PACKED;
102
103   /**
104    * Unique (random) identifier this peer will use to
105    * identify the finger (in future messages).
106    */
107   struct GNUNET_HashCode finger_id;
108
109   /**
110    * Random location in the respective layer where the
111    * random path of the finger setup terminated.
112    */
113   struct GNUNET_HashCode location;
114
115 };
116
117
118 /**
119  * Response to an event that causes a finger to die.
120  */
121 struct FingerDestroyMessage
122 {
123   /**
124    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_DESTROY
125    */
126   struct GNUNET_MessageHeader header;
127
128   /**
129    * Zero, for alignment.
130    */
131   uint32_t reserved GNUNET_PACKED;
132
133   /**
134    * Unique (random) identifier this peer will use to
135    * identify the finger (in future messages).
136    */
137   struct GNUNET_HashCode finger_id;
138
139 };
140
141
142 /**
143  * Send a message along a finger.
144  */
145 struct FingerRouteMessage
146 {
147   /**
148    * Type: #GNUNET_MESSAGE_TYPE_WDHT_FINGER_ROUTE
149    */
150   struct GNUNET_MessageHeader header;
151
152   /**
153    * Zero, for alignment.
154    */
155   uint32_t reserved GNUNET_PACKED;
156
157   /**
158    * Unique (random) identifier this peer will use to
159    * identify the finger (in future messages).
160    */
161   struct GNUNET_HashCode finger_id;
162
163   /* followed by payload to send along the finger */
164 };
165
166
167 /**
168  * P2P PUT message
169  */
170 struct PeerPutMessage
171 {
172   /**
173    * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_PUT
174    */
175   struct GNUNET_MessageHeader header;
176
177   /**
178    * Processing options
179    */
180   uint32_t options GNUNET_PACKED;
181
182   /**
183    * Content type.
184    */
185   uint32_t block_type GNUNET_PACKED;
186
187   /**
188    * Hop count
189    */
190   uint32_t hop_count GNUNET_PACKED;
191
192   /**
193    * Replication level for this message
194    * In the current implementation, this value is not used.
195    */
196   uint32_t desired_replication_level GNUNET_PACKED;
197
198   /**
199    * Length of the PUT path that follows (if tracked).
200    */
201   uint32_t put_path_length GNUNET_PACKED;
202
203   /**
204    * When does the content expire?
205    */
206   struct GNUNET_TIME_AbsoluteNBO expiration_time;
207
208   /**
209    * The key to store the value under.
210    */
211   struct GNUNET_HashCode key GNUNET_PACKED;
212
213   /* put path (if tracked) */
214
215   /* Payload */
216
217 };
218
219 /**
220  * P2P GET message
221  */
222 struct PeerGetMessage
223 {
224   /**
225    * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET
226    */
227   struct GNUNET_MessageHeader header;
228
229   /**
230    * Processing options
231    */
232   uint32_t options GNUNET_PACKED;
233
234   /**
235    * Desired content type.
236    */
237   uint32_t block_type GNUNET_PACKED;
238
239   /**
240    * Hop count
241    */
242   uint32_t hop_count GNUNET_PACKED;
243
244   /**
245    * Desired replication level for this request.
246    * In the current implementation, this value is not used.
247    */
248   uint32_t desired_replication_level GNUNET_PACKED;
249
250   /**
251    * Total number of peers in get path.
252    */
253   unsigned int get_path_length;
254
255   /**
256    * The key we are looking for.
257    */
258   struct GNUNET_HashCode key;
259
260   /* Get path. */
261   /* struct GNUNET_PeerIdentity[]*/
262 };
263
264
265 /**
266  * P2P Result message
267  */
268 struct PeerGetResultMessage
269 {
270   /**
271    * Type: #GNUNET_MESSAGE_TYPE_WDHT_P2P_GET_RESULT
272    */
273   struct GNUNET_MessageHeader header;
274
275   /**
276    * The type for the data.
277    */
278   uint32_t type GNUNET_PACKED;
279
280   /**
281    * Number of peers recorded in the outgoing path from source to the
282    * stored location of this message.
283    */
284   uint32_t put_path_length GNUNET_PACKED;
285
286   /**
287    * Length of the GET path that follows (if tracked).
288    */
289   uint32_t get_path_length GNUNET_PACKED;
290
291   /**
292    * Peer which queried for get and should get the result.
293    */
294   struct GNUNET_PeerIdentity querying_peer;
295
296   /**
297    * When does the content expire?
298    */
299   struct GNUNET_TIME_Absolute expiration_time;
300
301   /**
302    * The key of the corresponding GET request.
303    */
304   struct GNUNET_HashCode key;
305
306   /* put path (if tracked) */
307
308   /* get path (if tracked) */
309
310   /* Payload */
311
312 };
313
314 GNUNET_NETWORK_STRUCT_END
315
316 /**
317  * Entry in friend_peermap.
318  */
319 struct FriendInfo;
320
321
322 /**
323  * Information we keep per trail.
324  */
325 struct Trail
326 {
327
328   /**
329    * MDLL entry in the list of all trails with the same predecessor.
330    */
331   struct Tail *prev_succ;
332
333   /**
334    * MDLL entry in the list of all trails with the same predecessor.
335    */
336   struct Tail *next_succ;
337
338   /**
339    * MDLL entry in the list of all trails with the same predecessor.
340    */
341   struct Tail *prev_pred;
342
343   /**
344    * MDLL entry in the list of all trails with the same predecessor.
345    */
346   struct Tail *next_pred;
347
348   /**
349    * Our predecessor in the trail, NULL if we are initiator (?).
350    */
351   struct FriendInfo *pred;
352
353   /**
354    * Our successor in the trail, NULL if we are the last peer.
355    */
356   struct FriendInfo *succ;
357
358   /**
359    * Identifier of the trail with the predecessor.
360    */
361   struct GNUNET_HashCode pred_id;
362
363   /**
364    * Identifier of the trail with the successor.
365    */
366   struct GNUNET_HashCode succ_id;
367
368   /**
369    * When does this trail expire.
370    */
371   struct GNUNET_TIME_Absolute expiration_time;
372
373 };
374
375
376 /**
377  *  Entry in friend_peermap.
378  */
379 struct FriendInfo
380 {
381   /**
382    * Friend Identity
383    */
384   struct GNUNET_PeerIdentity id;
385
386   struct Tail *pred_head;
387
388   struct Tail *pred_tail;
389
390   struct Tail *succ_head;
391
392   struct Tail *succ_tail;
393
394   /**
395    * Core handle for sending messages to this friend.
396    * FIXME: use MQ?
397    */
398   struct GNUNET_CORE_TransmitHandle *th;
399
400 };
401
402
403
404 /**
405  * Task to timeout trails that have expired.
406  */
407 static struct GNUNET_SCHEDULER_Task *trail_timeout_task;
408
409 /**
410  * Identity of this peer.
411  */
412 static struct GNUNET_PeerIdentity my_identity;
413
414 /**
415  * Peer map of all the friends of a peer
416  */
417 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
418
419 /**
420  * Tail map, mapping tail identifiers to `struct Trail`s
421  */
422 static struct GNUNET_CONTAINER_MultiHashMap *tail_map;
423
424 /**
425  * Tail heap, organizing trails by expiration time.
426  */
427 static struct GNUNET_CONTAINER_Heap *tail_heap;
428
429 /**
430  * Handle to CORE.
431  */
432 static struct GNUNET_CORE_Handle *core_api;
433
434
435
436
437
438
439
440 /**
441  * Construct a trail setup message and forward it to target_friend
442  * @param source_peer Peer which wants to setup the trail
443  * @param ultimate_destination_finger_value Peer identity closest to this value
444  *                                          will be finger to @a source_peer
445  * @param best_known_destination Best known destination (could be finger or friend)
446  *                               which should get this message. In case it is
447  *                               friend, then it is same as target_friend
448  * @param target_friend Friend to which message is forwarded now.
449  * @param trail_length Total number of peers in trail setup so far.
450  * @param trail_peer_list Trail setup so far
451  * @param is_predecessor Is @a source_peer looking for trail to a predecessor or not.
452  * @param trail_id Unique identifier for the trail we are trying to setup.
453  * @param intermediate_trail_id Trail id of intermediate trail to reach to
454  *                              best_known_destination when its a finger. If not
455  *                              used then set to 0.
456  */
457 void
458 GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer,
459                                  uint64_t ultimate_destination_finger_value,
460                                  struct GNUNET_PeerIdentity best_known_destination,
461                                  struct FriendInfo *target_friend,
462                                  unsigned int trail_length,
463                                  const struct GNUNET_PeerIdentity *trail_peer_list,
464                                  unsigned int is_predecessor,
465                                  struct GNUNET_HashCode trail_id,
466                                  struct GNUNET_HashCode intermediate_trail_id)
467 {
468   struct P2PPendingMessage *pending;
469   struct PeerTrailSetupMessage *tsm;
470   struct GNUNET_PeerIdentity *peer_list;
471   size_t msize;
472
473   msize = sizeof (struct PeerTrailSetupMessage) +
474           (trail_length * sizeof (struct GNUNET_PeerIdentity));
475
476   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
477   {
478     GNUNET_break (0);
479     return;
480   }
481
482   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
483   {
484     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
485                                 1, GNUNET_NO);
486   }
487   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
488   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
489   tsm = (struct PeerTrailSetupMessage *) &pending[1];
490   pending->msg = &(tsm->header);
491   tsm->header.size = htons (msize);
492   tsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP);
493   tsm->final_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
494   tsm->source_peer = source_peer;
495   tsm->best_known_destination = best_known_destination;
496   tsm->is_predecessor = htonl (is_predecessor);
497   tsm->trail_id = trail_id;
498   tsm->intermediate_trail_id = intermediate_trail_id;
499
500   if (trail_length > 0)
501   {
502     peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
503     memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
504   }
505
506   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
507   target_friend->pending_count++;
508   process_friend_queue (target_friend);
509 }
510
511
512 /**
513  * Construct a trail setup result message and forward it to target friend.
514  * @param querying_peer Peer which sent the trail setup request and should get
515  *                      the result back.
516  * @param Finger Peer to which the trail has been setup to.
517  * @param target_friend Friend to which this message should be forwarded.
518  * @param trail_length Numbers of peers in the trail.
519  * @param trail_peer_list Peers which are part of the trail from
520  *                        querying_peer to Finger, NOT including them.
521  * @param is_predecessor Is @a Finger predecessor to @a querying_peer ?
522  * @param ultimate_destination_finger_value Value to which @a finger is the closest
523  *                                          peer.
524  * @param trail_id Unique identifier of the trail.
525  */
526 void
527 GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer,
528                                         struct GNUNET_PeerIdentity finger,
529                                         struct FriendInfo *target_friend,
530                                         unsigned int trail_length,
531                                         const struct GNUNET_PeerIdentity *trail_peer_list,
532                                         unsigned int is_predecessor,
533                                         uint64_t ultimate_destination_finger_value,
534                                         struct GNUNET_HashCode trail_id)
535 {
536   struct P2PPendingMessage *pending;
537   struct PeerTrailSetupResultMessage *tsrm;
538   struct GNUNET_PeerIdentity *peer_list;
539   size_t msize;
540
541   msize = sizeof (struct PeerTrailSetupResultMessage) +
542           (trail_length * sizeof (struct GNUNET_PeerIdentity));
543
544   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
545   {
546     GNUNET_break (0);
547     return;
548   }
549
550   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
551   {
552     GNUNET_STATISTICS_update (GDS_stats,
553                               gettext_noop ("# P2P messages dropped due to full queue"),
554                               1, GNUNET_NO);
555   }
556
557   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
558   pending->importance = 0;
559   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
560   tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
561   pending->msg = &tsrm->header;
562   tsrm->header.size = htons (msize);
563   tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT);
564   tsrm->querying_peer = querying_peer;
565   tsrm->finger_identity = finger;
566   tsrm->is_predecessor = htonl (is_predecessor);
567   tsrm->trail_id = trail_id;
568   tsrm->ulitmate_destination_finger_value =
569           GNUNET_htonll (ultimate_destination_finger_value);
570   peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
571   memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
572
573   /* Send the message to chosen friend. */
574   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
575   target_friend->pending_count++;
576   process_friend_queue (target_friend);
577 }
578
579 /**
580  * Send notify successor confirmation message.
581  * @param trail_id Unique Identifier of the trail.
582  * @param trail_direction Destination to Source.
583  * @param target_friend Friend to get this message next.
584  */
585 void
586 GDS_NEIGHBOURS_send_notify_succcessor_confirmation (struct GNUNET_HashCode trail_id,
587                                                     unsigned int trail_direction,
588                                                      struct FriendInfo *target_friend)
589 {
590   struct PeerNotifyConfirmationMessage *ncm;
591   struct P2PPendingMessage *pending;
592   size_t msize;
593
594   msize = sizeof (struct PeerNotifyConfirmationMessage);
595   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
596   {
597     GNUNET_break (0);
598     return;
599   }
600
601   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
602   {
603     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
604                                 1, GNUNET_NO);
605   }
606
607   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
608   pending->importance = 0;    /* FIXME */
609   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
610   ncm = (struct PeerNotifyConfirmationMessage *) &pending[1];
611   pending->msg = &ncm->header;
612   ncm->header.size = htons (msize);
613   ncm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION);
614   ncm->trail_id = trail_id;
615   ncm->trail_direction = htonl (trail_direction);
616
617   /* Send the message to chosen friend. */
618   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
619   target_friend->pending_count++;
620   process_friend_queue (target_friend);
621 }
622
623
624 /**
625  * Send trail rejection message to target friend
626  * @param source_peer Peer which is trying to setup the trail.
627  * @param ultimate_destination_finger_value Peer closest to this value will be
628  *                                          @a source_peer's finger
629  * @param congested_peer Peer which sent this message as it is congested.
630  * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
631  * @param trail_peer_list Trails seen so far in trail setup before getting rejected
632  *                        by congested_peer. This does NOT include @a source_peer
633  *                        and congested_peer.
634  * @param trail_length Total number of peers in trail_peer_list, NOT including
635  *                     @a source_peer and @a congested_peer
636  * @param trail_id Unique identifier of this trail.
637  * @param congestion_timeout Duration given by congested peer as an estimate of
638  *                           how long it may remain congested.
639  */
640 void
641 GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
642                                      uint64_t ultimate_destination_finger_value,
643                                      struct GNUNET_PeerIdentity congested_peer,
644                                      unsigned int is_predecessor,
645                                      const struct GNUNET_PeerIdentity *trail_peer_list,
646                                      unsigned int trail_length,
647                                      struct GNUNET_HashCode trail_id,
648                                      struct FriendInfo *target_friend,
649                                      const struct GNUNET_TIME_Relative congestion_timeout)
650 {
651   struct PeerTrailRejectionMessage *trm;
652   struct P2PPendingMessage *pending;
653   struct GNUNET_PeerIdentity *peer_list;
654   size_t msize;
655
656   msize = sizeof (struct PeerTrailRejectionMessage) +
657           (trail_length * sizeof (struct GNUNET_PeerIdentity));
658
659   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
660   {
661     GNUNET_break (0);
662     return;
663   }
664
665   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
666   {
667     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
668                                 1, GNUNET_NO);
669   }
670
671   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
672   pending->importance = 0;
673   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
674   trm = (struct PeerTrailRejectionMessage *)&pending[1];
675   pending->msg = &trm->header;
676   trm->header.size = htons (msize);
677   trm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION);
678   trm->source_peer = source_peer;
679   trm->congested_peer = congested_peer;
680   trm->congestion_time = congestion_timeout;
681   trm->is_predecessor = htonl (is_predecessor);
682   trm->trail_id = trail_id;
683   trm->ultimate_destination_finger_value =
684           GNUNET_htonll (ultimate_destination_finger_value);
685
686   peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
687   if (trail_length > 0)
688   {
689     memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
690   }
691
692   /* Send the message to chosen friend. */
693   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
694   target_friend->pending_count++;
695   process_friend_queue (target_friend);
696 }
697
698
699 /**
700  * Construct a verify successor message and forward it to target_friend.
701  * @param source_peer Peer which wants to verify its successor.
702  * @param successor Peer which is @a source_peer's current successor.
703  * @param trail_id Unique Identifier of trail from @a source_peer to @a successor,
704  *                 NOT including them.
705  * @param trail List of peers which are part of trail to reach from @a source_peer
706  *              to @a successor, NOT including them.
707  * @param trail_length Total number of peers in @a trail.
708  * @param target_friend Next friend to get this message.
709  */
710 void
711 GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
712                                               struct GNUNET_PeerIdentity successor,
713                                               struct GNUNET_HashCode trail_id,
714                                               struct GNUNET_PeerIdentity *trail,
715                                               unsigned int trail_length,
716                                               struct FriendInfo *target_friend)
717 {
718   struct PeerVerifySuccessorMessage *vsm;
719   struct P2PPendingMessage *pending;
720   struct GNUNET_PeerIdentity *peer_list;
721   size_t msize;
722
723   msize = sizeof (struct PeerVerifySuccessorMessage) +
724          (trail_length * sizeof (struct GNUNET_PeerIdentity));
725
726   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
727   {
728     GNUNET_break (0);
729     return;
730   }
731
732   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
733   {
734     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
735                                 1, GNUNET_NO);
736   }
737
738   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
739   pending->importance = 0;    /* FIXME */
740   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
741   vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
742   pending->msg = &vsm->header;
743   vsm->header.size = htons (msize);
744   vsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR);
745   vsm->source_peer = source_peer;
746   vsm->successor = successor;
747   vsm->trail_id = trail_id;
748   peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
749   memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
750
751   /* Send the message to chosen friend. */
752   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
753   target_friend->pending_count++;
754   process_friend_queue (target_friend);
755 }
756
757
758 /**
759  * FIXME: In every function we pass target friend except for this one.
760  * so, either change everything or this one. also, should se just store
761  * the pointer to friend in routing table rather than gnunet_peeridentity.
762  * if yes then we should keep friend info in.h  andmake lot of changes.
763  * Construct a trail teardown message and forward it to target friend.
764  *
765  * @param trail_id Unique identifier of the trail.
766  * @param trail_direction Direction of trail.
767  * @param target_friend Friend to get this message.
768  */
769 void
770 GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_HashCode *trail_id,
771                                     unsigned int trail_direction,
772                                     const struct GNUNET_PeerIdentity *peer)
773 {
774   struct PeerTrailTearDownMessage *ttdm;
775   struct P2PPendingMessage *pending;
776   struct FriendInfo *target_friend;
777   size_t msize;
778
779   msize = sizeof (struct PeerTrailTearDownMessage);
780   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
781   {
782     GNUNET_break (0);
783     return;
784   }
785
786   if (NULL == (target_friend =
787                GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)))
788   {
789     /* FIXME: In what case friend can be null. ?*/
790     GNUNET_break (0);
791     return;
792   }
793
794   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
795   {
796     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
797                                 1, GNUNET_NO);
798   }
799
800   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
801   pending->importance = 0;    /* FIXME */
802   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
803   ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
804   pending->msg = &ttdm->header;
805   ttdm->header.size = htons (msize);
806   ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN);
807   ttdm->trail_id = *trail_id;
808   ttdm->trail_direction = htonl (trail_direction);
809
810   /* Send the message to chosen friend. */
811   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
812   target_friend->pending_count++;
813   process_friend_queue (target_friend);
814 }
815
816
817 /**
818  * Construct a verify successor result message and send it to target_friend
819  * @param querying_peer Peer which sent the verify successor message.
820  * @param source_successor Current_successor of @a querying_peer.
821  * @param current_predecessor Current predecessor of @a successor. Could be same
822  *                            or different from @a querying_peer.
823  * @param trail_id Unique identifier of the trail from @a querying_peer to
824  *                 @a successor, NOT including them.
825  * @param trail List of peers which are part of trail from @a querying_peer to
826  *                 @a successor, NOT including them.
827  * @param trail_length Total number of peers in @a trail
828  * @param trail_direction Direction in which we are sending the message. In this
829  *                        case we are sending result from @a successor to @a querying_peer.
830  * @param target_friend Next friend to get this message.
831  */
832 void
833 GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying_peer,
834                                              struct GNUNET_PeerIdentity current_successor,
835                                              struct GNUNET_PeerIdentity probable_successor,
836                                              struct GNUNET_HashCode trail_id,
837                                              const struct GNUNET_PeerIdentity *trail,
838                                              unsigned int trail_length,
839                                              enum GDS_ROUTING_trail_direction trail_direction,
840                                              struct FriendInfo *target_friend)
841 {
842   struct PeerVerifySuccessorResultMessage *vsmr;
843   struct P2PPendingMessage *pending;
844   struct GNUNET_PeerIdentity *peer_list;
845   size_t msize;
846
847   msize = sizeof (struct PeerVerifySuccessorResultMessage) +
848           (trail_length * sizeof(struct GNUNET_PeerIdentity));
849
850   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
851   {
852     GNUNET_break (0);
853     return;
854   }
855
856   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
857   {
858     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
859                                 1, GNUNET_NO);
860   }
861
862   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
863   pending->importance = 0;    /* FIXME */
864   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
865   vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
866   pending->msg = &vsmr->header;
867   vsmr->header.size = htons (msize);
868   vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT);
869   vsmr->querying_peer = querying_peer;
870   vsmr->current_successor = current_successor;
871   vsmr->probable_successor = probable_successor;
872   vsmr->trail_direction = htonl (trail_direction);
873   vsmr->trail_id = trail_id;
874   peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
875   memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
876
877    /* Send the message to chosen friend. */
878   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
879   target_friend->pending_count++;
880   process_friend_queue (target_friend);
881 }
882
883 /**
884  * Construct a Put message and send it to target_peer.
885  * @param key Key for the content
886  * @param block_type Type of the block
887  * @param options Routing options
888  * @param desired_replication_level Desired replication count
889  * @param best_known_dest Peer to which this message should reach eventually,
890  *                        as it is best known destination to me.
891  * @param intermediate_trail_id Trail id in case
892  * @param target_peer Peer to which this message will be forwarded.
893  * @param hop_count Number of hops traversed so far.
894  * @param put_path_length Total number of peers in @a put_path
895  * @param put_path Number of peers traversed so far
896  * @param expiration_time When does the content expire
897  * @param data Content to store
898  * @param data_size Size of content @a data in bytes
899  */
900 void
901 GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
902                          enum GNUNET_BLOCK_Type block_type,
903                                            enum GNUNET_DHT_RouteOption options,
904                                            uint32_t desired_replication_level,
905                                            struct GNUNET_PeerIdentity best_known_dest,
906                                            struct GNUNET_HashCode intermediate_trail_id,
907                                            struct GNUNET_PeerIdentity *target_peer,
908                          uint32_t hop_count,
909                          uint32_t put_path_length,
910                          struct GNUNET_PeerIdentity *put_path,
911                          struct GNUNET_TIME_Absolute expiration_time,
912                          const void *data, size_t data_size)
913 {
914   struct PeerPutMessage *ppm;
915   struct P2PPendingMessage *pending;
916   struct FriendInfo *target_friend;
917   struct GNUNET_PeerIdentity *pp;
918   size_t msize;
919
920   msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
921           sizeof (struct PeerPutMessage);
922   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
923   {
924     put_path_length = 0;
925     msize = data_size + sizeof (struct PeerPutMessage);
926   }
927
928   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
929   {
930     DEBUG("msize = %lu\n",msize);
931     GNUNET_break (0);
932     return;
933   }
934
935   GNUNET_assert (NULL !=
936                  (target_friend =
937                   GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
938   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
939   pending->timeout = expiration_time;
940   ppm = (struct PeerPutMessage *) &pending[1];
941   pending->msg = &ppm->header;
942   ppm->header.size = htons (msize);
943   ppm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT);
944   ppm->options = htonl (options);
945   ppm->block_type = htonl (block_type);
946   ppm->hop_count = htonl (hop_count + 1);
947   ppm->desired_replication_level = htonl (desired_replication_level);
948   ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
949   ppm->best_known_destination = best_known_dest;
950   ppm->intermediate_trail_id = intermediate_trail_id;
951   ppm->key = *key;
952   pp = (struct GNUNET_PeerIdentity *) &ppm[1];
953   ppm->put_path_length = htonl (put_path_length);
954   if(put_path_length > 0)
955   {
956     memcpy (pp, put_path,
957             sizeof (struct GNUNET_PeerIdentity) * put_path_length);
958   }
959   memcpy (&pp[put_path_length], data, data_size);
960   GNUNET_assert (NULL != target_friend);
961   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
962   target_friend->pending_count++;
963   process_friend_queue (target_friend);
964 }
965
966
967 /**
968  * Handle the put request from the client.
969  * @param key Key for the content
970  * @param block_type Type of the block
971  * @param options Routing options
972  * @param desired_replication_level Desired replication count
973  * @param expiration_time When does the content expire
974  * @param data Content to store
975  * @param data_size Size of content @a data in bytes
976  */
977 void
978 GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
979                            enum GNUNET_BLOCK_Type block_type,
980                            enum GNUNET_DHT_RouteOption options,
981                            uint32_t desired_replication_level,
982                            struct GNUNET_TIME_Absolute expiration_time,
983                            const void *data, size_t data_size)
984 {
985   struct GNUNET_PeerIdentity best_known_dest;
986   struct GNUNET_HashCode intermediate_trail_id;
987   struct GNUNET_PeerIdentity next_hop;
988   uint64_t key_value;
989   struct Closest_Peer successor;
990
991   memcpy (&key_value, key, sizeof (uint64_t));
992   key_value = GNUNET_ntohll (key_value);
993   successor = find_local_best_known_next_hop (key_value,
994                                               GDS_FINGER_TYPE_NON_PREDECESSOR);
995   best_known_dest = successor.best_known_destination;
996   next_hop = successor.next_hop;
997   intermediate_trail_id = successor.trail_id;
998
999   if (0 == GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity))
1000   {
1001     DEBUG("\n PUT_REQUEST_SUCCESSFUL for key = %s",GNUNET_h2s(key));
1002     /* I am the destination. */
1003     GDS_DATACACHE_handle_put (expiration_time, key, 0, NULL,
1004                               block_type,data_size,data);
1005     GDS_CLIENTS_process_put (options, block_type, 0,
1006                              ntohl (desired_replication_level),
1007                              1, &my_identity, expiration_time, //FIXME: GNUNETnthoh something on expiration time.
1008                              key, data, data_size);
1009     return;
1010   }
1011   /* In case we are sending the request to  a finger, then send across all of its
1012    trail.*/
1013 #if ENABLE_MALICIOUS
1014   if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
1015                                             &successor.next_hop))
1016   {
1017     struct FingerInfo *next_hop_finger;
1018     unsigned int i;
1019
1020     next_hop_finger = &finger_table[successor.finger_table_index];
1021     for (i = 0; i < next_hop_finger->trails_count; i++)
1022     {
1023       if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
1024       {
1025         if(0 == next_hop_finger->trail_list[i].trail_length)
1026         {
1027            GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
1028                                     best_known_dest, intermediate_trail_id, &next_hop,
1029                                     0, 1, &my_identity, expiration_time,
1030                                     data, data_size);
1031            return;
1032         }
1033         next_hop = next_hop_finger->trail_list[i].trail_head->peer;
1034         GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
1035                                  best_known_dest,
1036                                  next_hop_finger->trail_list[i].trail_id,
1037                                  &next_hop, 0, 1, &my_identity,
1038                                  expiration_time,
1039                                  data, data_size);
1040        }
1041     }
1042     return;
1043   }
1044 #endif
1045  GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
1046                           best_known_dest, intermediate_trail_id, &next_hop,
1047                           0, 1, &my_identity, expiration_time,
1048                           data, data_size);
1049 }
1050
1051 /**
1052  * Construct a Get message and send it to target_peer.
1053  * @param key Key for the content
1054  * @param block_type Type of the block
1055  * @param options Routing options
1056  * @param desired_replication_level Desired replication count
1057  * @param best_known_dest Peer which should get this message. Same as target peer
1058  *                        if best_known_dest is a friend else its a finger.
1059  * @param intermediate_trail_id  Trail id to reach to @a best_known_dest
1060  *                              in case it is a finger else set to 0.
1061  * @param target_peer Peer to which this message will be forwarded.
1062  * @param hop_count Number of hops traversed so far.
1063  * @param data Content to store
1064  * @param data_size Size of content @a data in bytes
1065  * @param get_path_length Total number of peers in @a get_path
1066  * @param get_path Number of peers traversed so far
1067  */
1068 void
1069 GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
1070                          enum GNUNET_BLOCK_Type block_type,
1071                          enum GNUNET_DHT_RouteOption options,
1072                          uint32_t desired_replication_level,
1073                          struct GNUNET_PeerIdentity best_known_dest,
1074                          struct GNUNET_HashCode intermediate_trail_id,
1075                          struct GNUNET_PeerIdentity *target_peer,
1076                          uint32_t hop_count,
1077                          uint32_t get_path_length,
1078                          struct GNUNET_PeerIdentity *get_path)
1079 {
1080   struct PeerGetMessage *pgm;
1081   struct P2PPendingMessage *pending;
1082   struct FriendInfo *target_friend;
1083   struct GNUNET_PeerIdentity *gp;
1084   size_t msize;
1085
1086   msize = sizeof (struct PeerGetMessage) +
1087           (get_path_length * sizeof (struct GNUNET_PeerIdentity));
1088
1089   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1090   {
1091     GNUNET_break (0);
1092     return;
1093   }
1094   GNUNET_assert (NULL !=
1095                  (target_friend =
1096                   GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
1097
1098   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1099   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1100   pending->importance = 0;    /* FIXME */
1101   pgm = (struct PeerGetMessage *) &pending[1];
1102   pending->msg = &pgm->header;
1103   pgm->header.size = htons (msize);
1104   pgm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET);
1105   pgm->get_path_length = htonl (get_path_length);
1106   pgm->best_known_destination = best_known_dest;
1107   pgm->key = *key;
1108   pgm->intermediate_trail_id = intermediate_trail_id;
1109   pgm->hop_count = htonl (hop_count + 1);
1110   pgm->get_path_length = htonl (get_path_length);
1111   gp = (struct GNUNET_PeerIdentity *) &pgm[1];
1112   memcpy (gp, get_path,
1113           sizeof (struct GNUNET_PeerIdentity) * get_path_length);
1114   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1115   target_friend->pending_count++;
1116   process_friend_queue (target_friend);
1117 }
1118
1119
1120 /**
1121  * Handle the get request from the client file. If I am destination do
1122  * datacache put and return. Else find the target friend and forward message
1123  * to it.
1124  * @param key Key for the content
1125  * @param block_type Type of the block
1126  * @param options Routing options
1127  * @param desired_replication_level Desired replication count
1128  */
1129 void
1130 GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key,
1131                           enum GNUNET_BLOCK_Type block_type,
1132                           enum GNUNET_DHT_RouteOption options,
1133                           uint32_t desired_replication_level)
1134 {
1135   struct Closest_Peer successor;
1136   struct GNUNET_PeerIdentity best_known_dest;
1137   struct GNUNET_HashCode intermediate_trail_id;
1138   uint64_t key_value;
1139
1140   memcpy (&key_value, key, sizeof (uint64_t));
1141   key_value = GNUNET_ntohll (key_value);
1142
1143   successor = find_local_best_known_next_hop (key_value,
1144                                               GDS_FINGER_TYPE_NON_PREDECESSOR);
1145
1146   best_known_dest = successor.best_known_destination;
1147   intermediate_trail_id = successor.trail_id;
1148
1149   /* I am the destination. I have the data. */
1150   if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
1151                                             &best_known_dest))
1152   {
1153     GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
1154                               NULL, 0, 1, &my_identity, NULL,&my_identity);
1155     return;
1156   }
1157
1158 #if ENABLE_MALICIOUS
1159   struct GNUNET_PeerIdentity next_hop;
1160   if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
1161                                             &successor.next_hop))
1162   {
1163     struct FingerInfo *next_hop_finger;
1164     unsigned int i;
1165
1166     next_hop_finger = &finger_table[successor.finger_table_index];
1167     for (i = 0; i < next_hop_finger->trails_count; i++)
1168     {
1169       if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
1170       {
1171         if(0 == next_hop_finger->trail_list[i].trail_length)
1172         {
1173            GDS_NEIGHBOURS_send_get (key, block_type, options,
1174                                     desired_replication_level,
1175                                     best_known_dest,intermediate_trail_id,
1176                                     &successor.next_hop,
1177                                     0, 1, &my_identity);
1178            return;
1179         }
1180         next_hop = next_hop_finger->trail_list[i].trail_head->peer;
1181         GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level,
1182                                  best_known_dest,
1183                                  next_hop_finger->trail_list[i].trail_id,
1184                                  &next_hop, 0, 1, &my_identity);
1185        }
1186     }
1187     return;
1188   }
1189 #endif
1190   GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level,
1191                            best_known_dest,intermediate_trail_id, &successor.next_hop,
1192                            0, 1, &my_identity);
1193 }
1194
1195
1196 /**
1197  * Send the get result to requesting client.
1198  *
1199  * @param key Key of the requested data.
1200  * @param type Block type
1201  * @param target_peer Next peer to forward the message to.
1202  * @param source_peer Peer which has the data for the key.
1203  * @param put_path_length Number of peers in @a put_path
1204  * @param put_path Path taken to put the data at its stored location.
1205  * @param get_path_length Number of peers in @a get_path
1206  * @param get_path Path taken to reach to the location of the key.
1207  * @param expiration When will this result expire?
1208  * @param data Payload to store
1209  * @param data_size Size of the @a data
1210  */
1211 void
1212 GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
1213                                 enum GNUNET_BLOCK_Type type,
1214                                 const struct GNUNET_PeerIdentity *target_peer,
1215                                 const struct GNUNET_PeerIdentity *source_peer,
1216                                 unsigned int put_path_length,
1217                                 const struct GNUNET_PeerIdentity *put_path,
1218                                 unsigned int get_path_length,
1219                                 const struct GNUNET_PeerIdentity *get_path,
1220                                 struct GNUNET_TIME_Absolute expiration,
1221                                 const void *data, size_t data_size)
1222 {
1223   struct PeerGetResultMessage *get_result;
1224   struct GNUNET_PeerIdentity *paths;
1225   struct P2PPendingMessage *pending;
1226   struct FriendInfo *target_friend;
1227   int current_path_index;
1228   size_t msize;
1229
1230   msize = (put_path_length + get_path_length )* sizeof (struct GNUNET_PeerIdentity) +
1231           data_size +
1232           sizeof (struct PeerGetResultMessage);
1233
1234   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1235   {
1236     put_path_length = 0;
1237     msize = msize - put_path_length * sizeof (struct GNUNET_PeerIdentity);
1238   }
1239
1240   if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1241   {
1242     GNUNET_break(0);
1243     return;
1244   }
1245   current_path_index = 0;
1246   if(get_path_length > 0)
1247   {
1248     current_path_index = search_my_index(get_path, get_path_length);
1249     if (-1 == current_path_index)
1250     {
1251       GNUNET_break (0);
1252       return;
1253     }
1254     if ((get_path_length + 1) == current_path_index)
1255     {
1256       DEBUG ("Peer found twice in get path. Not allowed \n");
1257       GNUNET_break (0);
1258       return;
1259     }
1260   }
1261   if (0 == current_path_index)
1262   {
1263     DEBUG ("GET_RESULT TO CLIENT KEY = %s, Peer = %s",GNUNET_h2s(key),GNUNET_i2s(&my_identity));
1264     GDS_CLIENTS_handle_reply (expiration, key, get_path_length,
1265                               get_path, put_path_length,
1266                               put_path, type, data_size, data);
1267     return;
1268   }
1269
1270   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1271   pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1272   pending->importance = 0;
1273   get_result = (struct PeerGetResultMessage *)&pending[1];
1274   pending->msg = &get_result->header;
1275   get_result->header.size = htons (msize);
1276   get_result->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT);
1277   get_result->key = *key;
1278   get_result->querying_peer = *source_peer;
1279   get_result->expiration_time = expiration;
1280   get_result->get_path_length = htonl (get_path_length);
1281   get_result->put_path_length = htonl (put_path_length);
1282   paths = (struct GNUNET_PeerIdentity *)&get_result[1];
1283   memcpy (paths, put_path,
1284           put_path_length * sizeof (struct GNUNET_PeerIdentity));
1285   memcpy (&paths[put_path_length], get_path,
1286           get_path_length * sizeof (struct GNUNET_PeerIdentity));
1287   memcpy (&paths[put_path_length + get_path_length], data, data_size);
1288
1289   GNUNET_assert (NULL !=
1290                 (target_friend =
1291                  GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1292                                                     &get_path[current_path_index - 1])));
1293   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1294   target_friend->pending_count++;
1295   process_friend_queue (target_friend);
1296 }
1297
1298
1299 /**
1300  * Method called whenever a peer disconnects.
1301  *
1302  * @param cls closure
1303  * @param peer peer identity this notification is about
1304  */
1305 static void
1306 handle_core_disconnect (void *cls,
1307                         const struct GNUNET_PeerIdentity *peer)
1308 {
1309   struct FriendInfo *remove_friend;
1310
1311   /* If disconnected to own identity, then return. */
1312   if (0 == memcmp (&my_identity,
1313                    peer,
1314                    sizeof (struct GNUNET_PeerIdentity)))
1315     return;
1316
1317   if (NULL == (remove_friend =
1318                GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1319                                                   peer)))
1320   {
1321     GNUNET_break (0);
1322     return;
1323   }
1324
1325   GNUNET_assert (GNUNET_YES ==
1326                  GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
1327                                                        peer,
1328                                                        remove_friend));
1329   /* FIXME: do stuff */
1330 }
1331
1332
1333 /**
1334  * Method called whenever a peer connects.
1335  *
1336  * @param cls closure
1337  * @param peer_identity peer identity this notification is about
1338  */
1339 static void
1340 handle_core_connect (void *cls,
1341                      const struct GNUNET_PeerIdentity *peer_identity)
1342 {
1343   struct FriendInfo *friend;
1344
1345   /* Check for connect to self message */
1346   if (0 == memcmp (&my_identity,
1347                    peer_identity,
1348                    sizeof (struct GNUNET_PeerIdentity)))
1349     return;
1350
1351   /* If peer already exists in our friend_peermap, then exit. */
1352   if (GNUNET_YES ==
1353       GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
1354                                               peer_identity))
1355   {
1356     GNUNET_break (0);
1357     return;
1358   }
1359
1360   friend = GNUNET_new (struct FriendInfo);
1361   friend->id = *peer_identity;
1362
1363   GNUNET_assert (GNUNET_OK ==
1364                  GNUNET_CONTAINER_multipeermap_put (friend_peermap,
1365                                                     peer_identity,
1366                                                     friend,
1367                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1368   /* do work? */
1369 }
1370
1371
1372 /**
1373  * To be called on core init/fail.
1374  *
1375  * @param cls service closure
1376  * @param identity the public identity of this peer
1377  */
1378 static void
1379 core_init (void *cls,
1380            const struct GNUNET_PeerIdentity *identity)
1381 {
1382   my_identity = *identity;
1383 }
1384
1385
1386 /**
1387  * Handle a `struct FingerSetupMessage`.
1388  *
1389  * @param cls closure (NULL)
1390  * @param peer sender identity
1391  * @param message the setup message
1392  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1393  */
1394 static int
1395 handle_dht_p2p_finger_setup (void *cls,
1396                              const struct GNUNET_PeerIdentity *peer,
1397                              const struct GNUNET_MessageHeader *message)
1398 {
1399   const struct FingerSetupMessage *fsm;
1400
1401   fsm = (const struct FingerSetupMessage *) message;
1402
1403   return GNUNET_OK;
1404 }
1405
1406
1407
1408 /**
1409  * Initialize neighbours subsystem.
1410  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1411  */
1412 int
1413 GDS_NEIGHBOURS_init (void)
1414 {
1415   static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
1416     { &handle_dht_p2p_finger_setup,
1417       GNUNET_MESSAGE_TYPE_WDHT_FINGER_SETUP,
1418       sizeof (struct FingerSetupMessage) },
1419     {NULL, 0, 0}
1420   };
1421
1422 #if ENABLE_MALICIOUS
1423   act_malicious = 0;
1424 #endif
1425
1426   core_api =
1427     GNUNET_CORE_connect (GDS_cfg, NULL,
1428                          &core_init,
1429                          &handle_core_connect,
1430                          &handle_core_disconnect,
1431                          NULL, GNUNET_NO,
1432                          NULL, GNUNET_NO,
1433                          core_handlers);
1434
1435   if (NULL == core_api)
1436     return GNUNET_SYSERR;
1437
1438   //TODO: check size of this peer map?
1439   friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1440   return GNUNET_OK;
1441 }
1442
1443
1444 /**
1445  * Shutdown neighbours subsystem.
1446  */
1447 void
1448 GDS_NEIGHBOURS_done (void)
1449 {
1450   if (NULL == core_api)
1451     return;
1452   GNUNET_CORE_disconnect (core_api);
1453   core_api = NULL;
1454
1455   GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
1456   GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
1457   friend_peermap = NULL;
1458 }
1459
1460
1461 /**
1462  * Get my identity
1463  *
1464  * @return my identity
1465  */
1466 struct GNUNET_PeerIdentity
1467 GDS_NEIGHBOURS_get_my_id (void)
1468 {
1469   return my_identity;
1470 }
1471
1472 /* end of gnunet-service-wdht_neighbours.c */