Computing finger identity using libgcrypt functions.
[oweals/gnunet.git] / src / dht / gnunet-service-xdht_neighbours.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009-2013 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_nse_service.h"
34 #include "gnunet_ats_service.h"
35 #include "gnunet_core_service.h"
36 #include "gnunet_datacache_lib.h"
37 #include "gnunet_transport_service.h"
38 #include "gnunet_hello_lib.h"
39 #include "gnunet_dht_service.h"
40 #include "gnunet_statistics_service.h"
41 #include "gnunet-service-xdht.h"
42 #include "gnunet-service-xdht_clients.h"
43 #include "gnunet-service-xdht_datacache.h"
44 #include "gnunet-service-xdht_hello.h"
45 #include "gnunet-service-xdht_neighbours.h"
46 #include "gnunet-service-xdht_nse.h"
47 #include "gnunet-service-xdht_routing.h"
48 #include <fenv.h>
49 #include "dht.h"
50
51
52 /*TODO 
53  * 1. Remove extra comments - FIXME,TODO,SUPU
54  * 2. Use GNUNET_Log to debug
55  */
56
57 /**
58  * Maximum possible fingers of a peer.
59  */
60 #define MAX_FINGERS 256
61
62 /**
63  * Maximum allowed number of pending messages per friend peer.
64  */
65 #define MAXIMUM_PENDING_PER_FRIEND 64
66
67 /**
68  * How long at least to wait before sending another find finger trail request.
69  */
70 #define DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
71
72 /**
73  * How long at most to wait before sending another find finger trail request.
74  */
75 #define DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10)
76
77
78 GNUNET_NETWORK_STRUCT_BEGIN
79
80 /* FIXME:
81  * 1) Bloomfilter is not required for X-Vine.
82  * Keep the field now but remove it when implementing PUT/GET.
83  * 2) also, check the field of put/get/result if all are required for
84  * x-vine or not. */
85   
86 /**
87  * P2P PUT message
88  */
89 struct PeerPutMessage
90 {
91   /**
92    * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
93    */
94   struct GNUNET_MessageHeader header;
95
96   /**
97    * Processing options
98    */
99   uint32_t options GNUNET_PACKED;
100
101   /**
102    * Content type.
103    */
104   uint32_t type GNUNET_PACKED;
105
106   /**
107    * Hop count
108    */
109   uint32_t hop_count GNUNET_PACKED;
110
111   /**
112    * Replication level for this message
113    */
114   uint32_t desired_replication_level GNUNET_PACKED;
115
116   /**
117    * Length of the PUT path that follows (if tracked).
118    */
119   uint32_t put_path_length GNUNET_PACKED;
120
121   /**
122    * When does the content expire?
123    */
124   struct GNUNET_TIME_AbsoluteNBO expiration_time;
125
126   /**
127    * Bloomfilter (for peer identities) to stop circular routes
128    */
129   char bloomfilter[DHT_BLOOM_SIZE];
130
131   /**
132    * The key we are storing under.
133    */
134   struct GNUNET_HashCode key;
135
136   /* put path (if tracked) */
137
138   /* Payload */
139
140 };
141
142
143 /**
144  * P2P Result message
145  */
146 struct PeerResultMessage
147 {
148   /**
149    * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
150    */
151   struct GNUNET_MessageHeader header;
152
153   /**
154    * Content type.
155    */
156   uint32_t type GNUNET_PACKED;
157
158   /**
159    * Length of the PUT path that follows (if tracked).
160    */
161   uint32_t put_path_length GNUNET_PACKED;
162
163   /**
164    * Length of the GET path that follows (if tracked).
165    */
166   uint32_t get_path_length GNUNET_PACKED;
167
168   /**
169    * When does the content expire?
170    */
171   struct GNUNET_TIME_AbsoluteNBO expiration_time;
172
173   /**
174    * The key of the corresponding GET request.
175    */
176   struct GNUNET_HashCode key;
177
178   /* put path (if tracked) */
179
180   /* get path (if tracked) */
181
182   /* Payload */
183
184 };
185
186
187 /**
188  * P2P GET message
189  */
190 struct PeerGetMessage
191 {
192   /**
193    * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET
194    */
195   struct GNUNET_MessageHeader header;
196
197   /**
198    * Processing options
199    */
200   uint32_t options GNUNET_PACKED;
201
202   /**
203    * Desired content type.
204    */
205   uint32_t type GNUNET_PACKED;
206
207   /**
208    * Hop count
209    */
210   uint32_t hop_count GNUNET_PACKED;
211
212   /**
213    * Desired replication level for this request.
214    */
215   uint32_t desired_replication_level GNUNET_PACKED;
216
217   /**
218    * Size of the extended query.
219    */
220   uint32_t xquery_size;
221
222   /**
223    * Bloomfilter mutator.
224    */
225   uint32_t bf_mutator;
226
227   /**
228    * Bloomfilter (for peer identities) to stop circular routes
229    */
230   char bloomfilter[DHT_BLOOM_SIZE];
231
232   /**
233    * The key we are looking for.
234    */
235   struct GNUNET_HashCode key;
236
237 };
238
239
240 /**
241  * FIXME: I have defined this struct between GNUNET_NETWORK_STRUCT_BEGIN. Is
242  * it correct? Also, I am using the same struct inside finger info and trailsetup
243  * trailsetupresult message. Is it correct? Verify while testing. */
244  /**
245   * Linked List of peers which are part of trail to reach a particular Finger.
246   */
247 struct TrailPeerList
248 {
249    /**
250    * Pointer to next item in the list
251    */
252    struct TrailPeerList *next;
253
254    /**
255    * Pointer to previous item in the list
256    */
257    struct TrailPeerList *prev;
258    
259    /**
260     * An element in this trail list
261     */
262    struct GNUNET_PeerIdentity *peer;
263   
264 };
265
266
267 /**
268  * FIXME : I am using the same struct TrailPeerList in both finger info
269  * and peertrailsetupmessage. Verify if its okay.
270  * P2P Trail setup message
271  */
272 struct PeerTrailSetupMessage
273 {
274   /**
275    * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP
276    */
277   struct GNUNET_MessageHeader header;
278
279   /**
280    * Source peer which wants to find trail to one of its finger. 
281    */
282   struct GNUNET_PeerIdentity *source_peer;
283
284   /**
285    * Finger id to which we want to set up the trail to. 
286    */
287   struct GNUNET_PeerIdentity *destination_finger;
288
289   /**
290    * This field contains the peer to which this packet is forwarded.
291    */
292   struct GNUNET_PeerIdentity *current_destination;
293  
294   /**
295    * Head of trail list.
296    */
297   struct TrailPeerList *head;
298   
299   /**
300    * Tail of trail list.
301    */
302   struct TrailPeerList *tail;
303   
304 };
305
306
307 /**
308  * P2P Trail setup Result message
309  */
310 struct PeerTrailSetupResultMessage
311 {
312   /**
313    * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_RESULT_SETUP
314    */
315   struct GNUNET_MessageHeader header;
316   
317   /**
318    * Finger to which we have found the path. 
319    */
320   struct GNUNET_PeerIdentity *finger;
321
322   /**
323    * Peer which was looking for the trail to finger. 
324    */
325   struct GNUNET_PeerIdentity *destination_peer;
326
327   /**
328    * This field contains the peer to which this packet is forwarded.
329    */
330   struct GNUNET_PeerIdentity *current_destination;
331   
332   /**
333    * Head of trail list.
334    */
335   struct TrailPeerList *head;
336   
337   /**
338    * Tail of trail list.
339    */
340   struct TrailPeerList *tail;
341   
342 };
343
344 GNUNET_NETWORK_STRUCT_END
345
346
347 /**
348  * Linked list of messages to send to a particular other peer.
349  */
350 struct P2PPendingMessage
351 {
352   /**
353    * Pointer to next item in the list
354    */
355   struct P2PPendingMessage *next;
356
357   /**
358    * Pointer to previous item in the list
359    */
360   struct P2PPendingMessage *prev;
361
362   /**
363    * When does this message time out?
364    */
365   struct GNUNET_TIME_Absolute timeout;
366
367    /**
368    * Message importance level.  FIXME: used? useful?
369    */
370   unsigned int importance;
371
372   /**
373    * Actual message to be sent, allocated at the end of the struct:
374    * // msg = (cast) &pm[1];
375    * // memcpy (&pm[1], data, len);
376    */
377   const struct GNUNET_MessageHeader *msg;
378
379 };
380
381 /**
382  *  Entry in friend_peers map.
383  */
384 struct FriendInfo
385 {
386
387  /**
388   * What is the identity of the peer?
389   */
390   struct GNUNET_PeerIdentity id;
391
392  /**
393   * Count of outstanding messages for peer.
394   */
395  unsigned int pending_count;
396
397  /**
398   * Head of pending messages to be sent to this peer.
399   */
400  struct P2PPendingMessage *head;
401
402  /**
403   * Tail of pending messages to be sent to this peer.
404   */
405  struct P2PPendingMessage *tail;
406  
407  /**
408   * TODO - How and where to use this?
409   * Core handle for sending messages to this peer.
410   */
411  struct GNUNET_CORE_TransmitHandle *th;
412
413 };
414
415 /**
416  * Entry in finger_peers map.
417  */
418 struct FingerInfo
419 {
420   /**
421    * What is the identity of the finger peer?
422    */
423   struct GNUNET_PeerIdentity id;
424   
425   /**
426    * Start of the interval of keys for which this finger is responsible.
427    */
428   unsigned int interval_start;
429
430   /**
431    * End of the interval of keys for which this finger is responsible.
432    */
433   unsigned int interval_end;
434
435   /**
436    * Head of trail list.
437    */
438   struct TrailPeerList *head;
439
440   /**
441    * Tail of trail list.
442    */
443   struct TrailPeerList *tail;
444   
445 };
446
447
448 /**
449  * Task that sends FIND FINGER TRAIL requests.
450  */
451 static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task;
452
453 /**
454  * Identity of this peer.
455  */
456 static struct GNUNET_PeerIdentity my_identity;
457
458 /**
459  * FIXME: Not used anywhere in the code yet. 
460  * Hash of the identity of this peer.
461  */
462 static struct GNUNET_HashCode my_identity_hash;
463
464 /**
465  * Hash map of all the friends of a peer
466  */
467 static struct GNUNET_CONTAINER_MultiPeerMap *friend_peers;
468
469 /**
470  * Hash map of all the fingers of a peer
471  */
472 static struct GNUNET_CONTAINER_MultiPeerMap *finger_peers;
473
474 /**
475  * TODO: Ask whats the use of ATS.
476  * Handle to ATS.
477  */
478 static struct GNUNET_ATS_PerformanceHandle *atsAPI;
479
480 /**
481  * Handle to CORE.
482  */
483 static struct GNUNET_CORE_Handle *core_api;
484
485 /**
486  * The current finger index that we have found trail to.
487  */
488 static unsigned int current_finger_index;
489
490
491 /**
492  * Called when core is ready to send a message we asked for
493  * out to the destination. 
494  * 
495  * @param cls the 'struct FriendInfo' of the target friend peer
496  * @param size number of bytes available in buf
497  * @param buf where the callee should write the message
498  * @return number of bytes written to buf
499  */
500 static size_t
501 core_transmit_notify (void *cls, size_t size, void *buf)
502 {
503   struct FriendInfo *peer = cls;
504   char *cbuf = buf;
505   struct P2PPendingMessage *pending;
506   size_t off;
507   size_t msize;
508
509   peer->th = NULL;
510   while ((NULL != (pending = peer->head)) &&
511          (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us))
512   {
513     peer->pending_count--;
514     GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
515     GNUNET_free (pending);
516   }
517   if (pending == NULL)
518   {
519     /* no messages pending */
520     return 0;
521   }
522   if (buf == NULL)
523   {
524     peer->th =
525         GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
526                                            pending->importance,
527                                            GNUNET_TIME_absolute_get_remaining
528                                            (pending->timeout), &peer->id,
529                                            ntohs (pending->msg->size),
530                                            &core_transmit_notify, peer);
531     GNUNET_break (NULL != peer->th);
532     return 0;
533   }
534   off = 0;
535   while ((NULL != (pending = peer->head)) &&
536          (size - off >= (msize = ntohs (pending->msg->size))))
537   {
538     GNUNET_STATISTICS_update (GDS_stats,
539                               gettext_noop
540                               ("# Bytes transmitted to other peers"), msize,
541                               GNUNET_NO);
542     memcpy (&cbuf[off], pending->msg, msize);
543     off += msize;
544     peer->pending_count--;
545     GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
546     GNUNET_free (pending);
547   }
548   if (peer->head != NULL)
549   {
550     peer->th =
551         GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
552                                            pending->importance,
553                                            GNUNET_TIME_absolute_get_remaining
554                                            (pending->timeout), &peer->id, msize,
555                                            &core_transmit_notify, peer);
556     GNUNET_break (NULL != peer->th);
557   }
558   return off;
559 }
560
561
562 /**
563  * Transmit all messages in the friend's message queue.
564  *
565  * @param peer message queue to process
566  */
567 static void
568 process_friend_queue (struct FriendInfo *peer)
569 {
570   struct P2PPendingMessage *pending;
571
572   if (NULL == (pending = peer->head))
573     return;
574   if (NULL != peer->th)
575     return;
576   GNUNET_STATISTICS_update (GDS_stats,
577                             gettext_noop
578                             ("# Bytes of bandwidth requested from core"),
579                             ntohs (pending->msg->size), GNUNET_NO);
580   
581   /*FIXME : here I don't know the use of importance, time out
582     Will check at run time if its all correct. */
583   peer->th =
584       GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
585                                          pending->importance,
586                                          GNUNET_TIME_absolute_get_remaining
587                                          (pending->timeout), &peer->id,
588                                          ntohs (pending->msg->size),
589                                          &core_transmit_notify, peer);
590   GNUNET_break (NULL != peer->th);
591 }
592
593
594 /**
595  * FIXME: Check the parameters. 
596  * Set up the trial message and forwards this message to friend. 
597  * 
598  * @param Finger id to which we want to setup the trail.
599  * @param Friend id through which we will try to setup the trail.
600  */
601 void
602 GDS_NEIGHBOURS_trail_setup(struct GNUNET_PeerIdentity *finger_id,
603                                   struct FriendInfo *target_friend)
604 {
605   /*
606   * FIXME: check if pending message actually contains the correct data.
607   */
608   struct P2PPendingMessage *pending;
609   /* FIXME: why I have defined as **? verify by testing. */
610   struct PeerTrailSetupMessage *tsm;
611   
612   if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
613   {
614     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
615                                 1, GNUNET_NO);
616   }
617   
618   /* SUPU: Verify if this copy between pending message, tsm is correct? */
619   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
620   /*SUPU: What does this code do? Does this initialize pending with
621    values of tsm? */
622   tsm = (struct PeerTrailSetupMessage *) &pending[1];
623   pending->msg = &tsm->header;
624   tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP);
625   tsm->destination_finger = finger_id;
626   tsm->source_peer = &my_identity;
627   GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
628   target_friend->pending_count++;
629   process_friend_queue(target_friend);
630 }
631
632
633 /**FIXME: Old implementation just to remove error
634  * TODO: Modify this function to handle our get request. 
635  * Perform a GET operation.  Forwards the given request to other
636  * peers.  Does not lookup the key locally.  May do nothing if this is
637  * the only peer in the network (or if we are the closest peer in the
638  * network).
639  *
640  * @param type type of the block
641  * @param options routing options
642  * @param desired_replication_level desired replication count
643  * @param hop_count how many hops did this request traverse so far?
644  * @param key key for the content
645  * @param xquery extended query
646  * @param xquery_size number of bytes in @a xquery
647  * @param reply_bf bloomfilter to filter duplicates
648  * @param reply_bf_mutator mutator for @a reply_bf
649  * @param peer_bf filter for peers not to select (again)
650  */
651 void
652 GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
653                            enum GNUNET_DHT_RouteOption options,
654                            uint32_t desired_replication_level,
655                            uint32_t hop_count, const struct GNUNET_HashCode * key,
656                            const void *xquery, size_t xquery_size,
657                            const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
658                            uint32_t reply_bf_mutator,
659                            struct GNUNET_CONTAINER_BloomFilter *peer_bf)
660 {
661
662 }
663
664 /**FIXME: Old implementation just to remove error.
665  * TODO: Modify this function to handle our put request. 
666  * Perform a PUT operation.   Forwards the given request to other
667  * peers.   Does not store the data locally.  Does not give the
668  * data to local clients.  May do nothing if this is the only
669  * peer in the network (or if we are the closest peer in the
670  * network).
671  *
672  * @param type type of the block
673  * @param options routing options
674  * @param desired_replication_level desired replication count
675  * @param expiration_time when does the content expire
676  * @param hop_count how many hops has this message traversed so far
677  * @param bf Bloom filter of peers this PUT has already traversed
678  * @param key key for the content
679  * @param put_path_length number of entries in @a put_path
680  * @param put_path peers this request has traversed so far (if tracked)
681  * @param data payload to store
682  * @param data_size number of bytes in @a data
683  */
684 void
685 GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
686                            enum GNUNET_DHT_RouteOption options,
687                            uint32_t desired_replication_level,
688                            struct GNUNET_TIME_Absolute expiration_time,
689                            uint32_t hop_count,
690                            struct GNUNET_CONTAINER_BloomFilter *bf,
691                            const struct GNUNET_HashCode *key,
692                            unsigned int put_path_length,
693                            struct GNUNET_PeerIdentity *put_path,
694                            const void *data, size_t data_size)
695 {
696
697 }
698
699
700 /**FIXME: Old implementation just to remove error.
701  * Handle a reply (route to origin).  Only forwards the reply back to
702  * other peers waiting for it.  Does not do local caching or
703  * forwarding to local clients.
704  *
705  * @param target neighbour that should receive the block (if still connected)
706  * @param type type of the block
707  * @param expiration_time when does the content expire
708  * @param key key for the content
709  * @param put_path_length number of entries in put_path
710  * @param put_path peers the original PUT traversed (if tracked)
711  * @param get_path_length number of entries in put_path
712  * @param get_path peers this reply has traversed so far (if tracked)
713  * @param data payload of the reply
714  * @param data_size number of bytes in data
715  */
716 void
717 GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
718                              enum GNUNET_BLOCK_Type type,
719                              struct GNUNET_TIME_Absolute expiration_time,
720                              const struct GNUNET_HashCode * key,
721                              unsigned int put_path_length,
722                              const struct GNUNET_PeerIdentity *put_path,
723                              unsigned int get_path_length,
724                              const struct GNUNET_PeerIdentity *get_path,
725                              const void *data, size_t data_size)
726 {
727     
728 }
729
730
731 /**
732  * SUPU: Check again. 
733  * I have written a code where 
734  * 1. I choose a random index from 0 to current size of my map.
735  * 2. Create an iterator.
736  * 3. set the iterator value to the current index id.
737  * 4. get the element stored at that index id.
738  * 5. return the index to calling function.
739  * I have not yet tested this function and I am not sure if its correct. 
740  * Randomly choose one of your friends from the friends_peer map
741  * @return Friend
742  */
743 static struct FriendInfo *
744 get_random_friend()
745 {  
746   unsigned int current_size;
747   unsigned int *index; 
748   unsigned int j = 0;
749   struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
750   struct GNUNET_PeerIdentity key_ret;
751   struct FriendInfo *friend;
752   
753   current_size = GNUNET_CONTAINER_multipeermap_size(friend_peers);
754   
755   /* Element stored at this index in friend_peers map should be chosen friend. */
756   index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
757   
758   /* Create an iterator for friend_peers map. */
759   iter = GNUNET_CONTAINER_multipeermap_iterator_create(friend_peers);
760   
761   /* Set the position of iterator to index. */
762   while(j < (*index))
763   {
764     if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,NULL,NULL))
765       j++;
766     else 
767       return NULL;
768   }  
769   
770   if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(iter,&key_ret,(const void **)&friend))
771   {
772     return friend;
773   }
774
775   return NULL;
776 }
777
778
779 /**
780  * Find finger id to which we want to setup the trail
781  * @return finger id 
782  */
783 static
784 struct GNUNET_PeerIdentity *
785 compute_finger_identity()
786 {
787   struct GNUNET_PeerIdentity *finger_identity;  
788   
789   finger_identity = GNUNET_CRYPTO_compute_finger(&my_identity,current_finger_index);
790   
791   current_finger_index = (current_finger_index+1) % MAX_FINGERS;
792   
793   /* Check if you already have an entry in finger_peers for this finger_id.
794      If yes then again look for a new finger_id.
795      FIXME: Should we return NULL here? 
796    if(NULL != GNUNET_CONTAINER_multipeermap_get(finger_peers,finger_peer_id))
797    {
798      finger_peer_id = compute_finger_identity();
799    }*/
800   return finger_identity;
801 }
802
803 /**
804  * TODO: Implement after testing friend/finger map.
805  * TODO: Handle the case when we already have a trail to our predecessor in
806  * the network. 
807  * This function will be needed when we are handling node joins/fails
808  * to maintain correct pointer to our predecessor and successor in the network. 
809  * Find immediate predecessor in the network.
810  * @param me my own identity
811  * @return peer identity of immediate predecessor.
812  */
813 static
814 struct GNUNET_PeerIdentity *
815 find_immediate_predecessor()
816 {
817   /* Using your own peer identity, calculate your predecessor
818    * in the network. Try to setup path to this predecessor using
819    * the same logic as used for other fingers. 
820    * If we already have a trail to our predecessor then send NULL and 
821    * calling function should be able to handle that case.
822   */
823   return NULL;
824 }
825
826
827 /**
828  * Task to send a find finger trail message. We attempt to find trail
829  * to our finger in the network.
830  *
831  * @param cls closure for this task
832  * @param tc the context under which the task is running
833  */
834 static void
835 send_find_finger_trail_message (void *cls,
836                         const struct GNUNET_SCHEDULER_TaskContext *tc)
837 {
838   struct GNUNET_PeerIdentity *finger_peer_id;
839   struct FriendInfo *friend_peer_id;
840   struct GNUNET_TIME_Relative next_send_time;
841  
842   /* We already have found trail to each of our possible fingers in the network. */
843   if (GNUNET_CONTAINER_multipeermap_size(finger_peers) == MAX_FINGERS)
844   {
845     /* We can find trail to our immediate predecessor in the network. */  
846     finger_peer_id = find_immediate_predecessor();  
847     if(NULL == finger_peer_id)
848     {
849       /* We already have a trail to reach to immediate predecessor. */
850       goto new_find_trail_request;
851     }
852   }
853   else
854   {
855     /* Find the finger_peer_id for which we want to setup the trail */
856     finger_peer_id = compute_finger_identity();
857   }
858   
859   /* Choose a friend randomly from your friend_peers map. */
860   friend_peer_id = get_random_friend();
861   
862   /* We found a friend.*/
863   if(NULL != friend_peer_id)
864     GDS_NEIGHBOURS_trail_setup(finger_peer_id, friend_peer_id);
865   
866   
867   new_find_trail_request:
868
869   next_send_time.rel_value_us =
870       DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
871       GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
872                                 DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us /
873                                 (current_finger_index + 1));
874  
875   find_finger_trail_task =
876       GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message,
877                                     NULL);
878 }
879
880
881 /**
882  * Method called whenever a peer connects.
883  *
884  * @param cls closure
885  * @param peer peer identity this notification is about
886  */
887 static void
888 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
889 {
890   struct FriendInfo *ret;
891
892   /* Check for connect to self message */
893   if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
894     return;
895
896   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
897               "Connected to %s\n",
898               GNUNET_i2s (peer));
899   
900   /* If peer already exists in our friend_peers, then exit. */
901   if (GNUNET_YES ==
902       GNUNET_CONTAINER_multipeermap_contains (friend_peers,
903                                               peer))
904   {
905     GNUNET_break (0);
906     return;
907   }
908
909   GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1,
910                             GNUNET_NO);
911
912   ret = GNUNET_new (struct FriendInfo);
913   ret->id = *peer;
914
915   GNUNET_assert (GNUNET_OK ==
916                  GNUNET_CONTAINER_multipeermap_put (friend_peers,
917                                                     peer, ret,
918                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
919
920   /* got a first connection, good time to start with FIND FINGER TRAIL requests... */
921   if (1 == GNUNET_CONTAINER_multipeermap_size(friend_peers))
922     find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
923 }
924
925
926 /**
927  * FIXME: Implement after testing finger/friend table setup.
928  * Method called whenever a peer disconnects.
929  *
930  * @param cls closure
931  * @param peer peer identity this notification is about
932  */
933 static void
934 handle_core_disconnect (void *cls,
935                         const struct GNUNET_PeerIdentity *peer)
936 {
937   /**
938    * 1. remove the friend from the friend map.
939    * 2. remove the trail for the fingers for which this peer was the first hop.
940    * 3. start send_find_finger_trail for these fingers to find a new trail 
941    * in the network.
942    * 4. Also when a node gets disconnected, how should we update pointers of its
943    * immediate successor and predecessor in the network ?
944    * 5. Also how do we distribute the keys in the network?
945    * 6. Here is case where we started put operation but a peer got disconnected and 
946       we removed the entry from the table. How to handle such a case. 
947    */
948 }
949
950
951 /**
952  * To be called on core init/fail.
953  *
954  * @param cls service closure
955  * @param identity the public identity of this peer
956  */
957 static void
958 core_init (void *cls,
959            const struct GNUNET_PeerIdentity *identity)
960 {
961   my_identity = *identity;
962   GNUNET_CRYPTO_hash (identity,
963                       sizeof (struct GNUNET_PeerIdentity),
964                       &my_identity_hash);
965 }
966
967
968 /**
969  * Core handler for p2p put requests.
970  *
971  * @param cls closure
972  * @param peer sender of the request
973  * @param message message
974  * @param peer peer identity this notification is about
975  * @return #GNUNET_OK to keep the connection open,
976  *         #GNUNET_SYSERR to close it (signal serious error)
977  */
978 static int
979 handle_dht_p2p_put (void *cls,
980                     const struct GNUNET_PeerIdentity *peer,
981                     const struct GNUNET_MessageHeader *message)
982 {
983     /**
984      1. Search the friend,finger and check your own id to find the closest
985      * predecessor the given key. --> find_predecessor()
986      2. If self then datache_store
987      3. If friend, then add to peer queue 
988      4. If finger, then add to the peer queue of the first hop.
989      * in put message also maintain a field current_destination and use
990      * same logic as trail setup to understand if you are just part of trail
991      * to reach to a particular peer or you are endpoint of trail or just a friend.
992      * 
993      */
994   return 0;
995 }
996
997
998 /**
999  * Core handler for p2p get requests.
1000  *
1001  * @param cls closure
1002  * @param peer sender of the request
1003  * @param message message
1004  * @return #GNUNET_OK to keep the connection open,
1005  *         #GNUNET_SYSERR to close it (signal serious error)
1006  */
1007 static int
1008 handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
1009                     const struct GNUNET_MessageHeader *message)
1010 {
1011   return 0;
1012 }
1013
1014
1015 /**
1016  * Core handler for p2p result messages.
1017  *
1018  * @param cls closure
1019  * @param message message
1020  * @param peer peer identity this notification is about
1021  * @return #GNUNET_YES (do not cut p2p connection)
1022  */
1023 static int
1024 handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer,
1025                        const struct GNUNET_MessageHeader *message)
1026 {
1027   return 0;
1028 }
1029
1030
1031 /**
1032  * FIXME:1. Check if current_destination field is set correctly. 
1033  * 2. Is it correct to use GNUNET_CMP_PEER_IDENTITY to find out the successor
1034  * of a finger. 
1035  * 3. We should check the interval of the keys for which a peer is responsible
1036  * when we are looking to find the correct peer to store a key. But 
1037  * --> How do we maintain this interval?
1038  * --> Should we check this interval when we are looking for trail to a finger
1039  * as in this function? 
1040  * The code flow seems to be very large. Could do better. 
1041  * @param destination peer id's predecessor we are looking for. 
1042  * @return
1043  */
1044 static struct GNUNET_PeerIdentity *
1045 find_successor(struct GNUNET_PeerIdentity *destination, struct GNUNET_PeerIdentity *current_destination)
1046 {
1047   unsigned int friend_index;
1048   unsigned int finger_index;
1049   struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1050   struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter;
1051   struct GNUNET_PeerIdentity key_ret;
1052   struct FriendInfo *friend;
1053   struct FingerInfo *finger;
1054   struct GNUNET_PeerIdentity *current_successor;
1055   
1056   /* FIXME: Temporary field used to understand if we got a friend or finger
1057      as next successor. find something better.*/
1058   int successor;
1059   int finger_peer = 0;
1060   int friend_peer = 1;  
1061   int me = 2;
1062   
1063   current_successor = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1064   
1065   /* initialize current_successor with your own identity.*/
1066   memcpy(current_successor,&my_identity,sizeof(struct GNUNET_PeerIdentity));
1067   successor = me;
1068   
1069   friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peers); 
1070   
1071   /*iterate over friend map till you reach a peer id such that destination <= peer id */ 
1072   for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peers); friend_index++)
1073   {
1074     if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend)) 
1075     {
1076       if(0 > GNUNET_CRYPTO_cmp_peer_identity(&friend->id,destination) ||
1077         (0 == GNUNET_CRYPTO_cmp_peer_identity(&friend->id,destination)))
1078       {
1079         /* If yes then check if finger <= current_successor */
1080         if(0 < GNUNET_CRYPTO_cmp_peer_identity(&friend->id,current_successor) ||
1081           (0 == GNUNET_CRYPTO_cmp_peer_identity(&friend->id,current_successor)))
1082         {
1083           memcpy(current_successor,friend,sizeof(struct GNUNET_PeerIdentity));
1084           successor = friend_peer;
1085         }
1086       }   
1087     }
1088   }
1089   
1090
1091   finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peers);  
1092   /*iterate over finger map till you reach a peer id such that destination <= peer id */
1093   for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peers); finger_index++)
1094   {
1095     if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger)) 
1096     {
1097        if(0 > GNUNET_CRYPTO_cmp_peer_identity(&finger->id,destination) ||
1098          (0 == GNUNET_CRYPTO_cmp_peer_identity(&finger->id,destination)))
1099        {
1100          /* If yes then check if finger <= current_friend_successor */
1101          if(0 < GNUNET_CRYPTO_cmp_peer_identity(&finger->id,current_successor) 
1102          || (0 == GNUNET_CRYPTO_cmp_peer_identity(&finger->id,current_successor)))
1103          {
1104            memcpy(current_successor,finger,sizeof(struct GNUNET_PeerIdentity));
1105            successor = finger_peer;
1106          } 
1107        } 
1108     }
1109   }
1110   
1111   if(successor == finger_peer)
1112   { 
1113     memcpy(current_destination,current_successor,sizeof(struct GNUNET_PeerIdentity));
1114   }
1115   else
1116   {
1117     /* The successor is either my_identity or friend. */  
1118     current_destination = NULL;
1119   }
1120   
1121   return current_successor;
1122 }
1123
1124
1125 /* Traverse the trail list to find the prev hop to store in routing table. */
1126 static
1127 struct GNUNET_PeerIdentity *
1128 find_trail_list_prev_hop(struct PeerTrailSetupMessage *trail_result)
1129 {
1130   /*FIXME: I don't see any function in existing dll implementation, to 
1131    just read the dll backward or forward. So, I would implement one here. 
1132    * As no one else uses this functionality so I guess its okay to just
1133    * implement it here.  */ 
1134   return NULL;
1135 }
1136
1137
1138 /**
1139  * FIXME: 
1140  * 1. Check if we are maintaining the 64k size of struct PeerTrailSetupMessage.
1141  * when we add ourself to the trail list. 
1142  * 2. Ensure every case is handled for current_destination. 
1143  * Core handler for P2P trail setup message.
1144  * @param cls closure
1145  * @param message message
1146  * @param peer peer identity this notification is about
1147  * @return #GNUNET_YES 
1148  */
1149 static int
1150 handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer,
1151                     const struct GNUNET_MessageHeader *message)
1152 {
1153   struct PeerTrailSetupMessage *trail_setup; 
1154   struct GNUNET_PeerIdentity *next_hop;
1155   struct GNUNET_PeerIdentity *prev_hop; 
1156   struct FriendInfo *friend;
1157   struct TrailPeerList *peer_entry;
1158   struct P2PPendingMessage *pending;
1159   
1160   uint16_t msize;
1161   
1162   msize = ntohs (message->size);
1163   if (msize < sizeof (struct PeerTrailSetupMessage))
1164   {
1165     GNUNET_break_op (0);
1166     return GNUNET_YES;
1167   }
1168   
1169   trail_setup = (struct PeerTrailSetupMessage *) message;
1170   
1171   GNUNET_STATISTICS_update (GDS_stats,
1172                             gettext_noop ("# TRAIL SETUP requests received"), 1,
1173                             GNUNET_NO);
1174   GNUNET_STATISTICS_update (GDS_stats,
1175                             gettext_noop ("# TRAIL SETUP bytes received"), msize,
1176                             GNUNET_NO);
1177   
1178   
1179   /* Check the value of current_destination and handle the respective case. */
1180   if(trail_setup->current_destination == NULL)
1181   {
1182     /* Find the next peer to pass the trail setup message. */  
1183     next_hop = find_successor(trail_setup->destination_finger,trail_setup->current_destination);
1184   }
1185   else if( 0 == (GNUNET_CRYPTO_cmp_peer_identity(trail_setup->current_destination,&my_identity)))
1186   {
1187     /* I am current destination, find the next peer to pass the trail setup message. */  
1188     next_hop = find_successor(trail_setup->destination_finger,trail_setup->current_destination);  
1189   }
1190   else
1191   {
1192     /* I am part of the trail to reach to current_destination. */
1193     next_hop = GDS_Routing_search(trail_setup->source_peer, trail_setup->current_destination, trail_setup->tail->peer);
1194   }
1195  
1196   
1197   if(0 == (GNUNET_CRYPTO_cmp_peer_identity(next_hop,&my_identity)))
1198   {
1199     /* I am the closest successor of the destination finger in the network. */
1200     /*TODO::
1201       1. Prepare a trail setup result message.
1202       2. Add yourself to trail list. 
1203       3. send packet to last element in the list. 
1204     */
1205     return GNUNET_YES;
1206   }
1207   
1208   /* FIXME:
1209    * Do we really need to pass the whole trail_setup? I guess
1210    * we can just pass the double linked list. 
1211   */
1212   prev_hop = find_trail_list_prev_hop(trail_setup);
1213      
1214   GDS_ROUTING_add(trail_setup->source_peer,trail_setup->current_destination,prev_hop,next_hop);
1215  
1216   peer_entry = GNUNET_malloc (sizeof (struct TrailPeerList));
1217   peer_entry->peer = &my_identity;
1218   peer_entry->next = NULL;
1219   peer_entry->prev = NULL;
1220   
1221   /*SUPU what is this stupid code that I have written. */
1222   GNUNET_CONTAINER_DLL_insert_tail(trail_setup->head->next,trail_setup->tail->prev,peer_entry);
1223   
1224   /* Find the struct FriendInfo for next_hop peer id. */
1225   friend = GNUNET_CONTAINER_multipeermap_get(friend_peers,next_hop);
1226   
1227   if (friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1228   {
1229     GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1230                                 1, GNUNET_NO);
1231   }
1232   
1233   /* Send trail setup message to next hop friend. */
1234   pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
1235   
1236   /* FIXME: Check if we are properly initializing pending. */
1237   trail_setup = (struct PeerTrailSetupMessage *) &pending[1];
1238   pending->msg = &trail_setup->header;
1239   GNUNET_CONTAINER_DLL_insert_tail (friend->head, friend->tail, pending);
1240   friend->pending_count++;
1241   process_friend_queue(friend);
1242   return GNUNET_YES;
1243 }
1244
1245
1246 /* Add an entry to finger table. */
1247 static 
1248 void finger_table_add(struct PeerTrailSetupResultMessage *result)
1249 {
1250     /* 1. create a struct FingerInfo and copy respective members
1251      * of result into this struct. 
1252      * Add the whole trail in your finger table, 
1253      also add interval. */
1254 }
1255
1256
1257 /* Traverse the trail list to find the next hop to pass the result message. */
1258 static
1259 struct GNUNET_PeerIdentity *
1260 find_trail_list_next_hop(struct PeerTrailSetupResultMessage *trail_result)
1261 {
1262   /* Setup the current_destination value to new next hop found. */
1263   return NULL;
1264 }
1265
1266
1267 /**
1268  * Core handle for p2p trail construction result messages.
1269  * @param cls closure
1270  * @param message message
1271  * @param peer peer identity this notification is about
1272  * @return #GNUNET_YES (do not cut p2p connection)
1273  * @return
1274  */
1275 static int
1276 handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
1277                     const struct GNUNET_MessageHeader *message)
1278 {
1279   /* FIXME: Should it be const? */
1280   struct PeerTrailSetupResultMessage *trail_result;
1281   struct GNUNET_PeerIdentity *next_hop;
1282   struct FriendInfo *friend;
1283   struct P2PPendingMessage *pending;
1284   trail_result = (struct PeerTrailSetupResultMessage *) message;   
1285  
1286   uint16_t msize;
1287    
1288   msize = ntohs (message->size);
1289   if (msize < sizeof (struct PeerTrailSetupResultMessage))
1290   {
1291     GNUNET_break_op (0);
1292     return GNUNET_YES;
1293   }  
1294   
1295   /* This should always be the case. */
1296   if( 0 == (GNUNET_CRYPTO_cmp_peer_identity(trail_result->current_destination,&my_identity)))
1297   {
1298     /* Am I the destination ? */
1299     if( 0 == (GNUNET_CRYPTO_cmp_peer_identity(trail_result->destination_peer,&my_identity)))
1300     {
1301       /* I am the destination. Add the trail to my finger table. */
1302       finger_table_add(trail_result);
1303       return GNUNET_YES;
1304     }
1305     else
1306     {
1307       /* Find the next peer in the trail list to pass the message to. */
1308       next_hop = find_trail_list_next_hop(trail_result);
1309       
1310       /* Find the struct FriendInfo for next_hop peer id. */
1311       friend = GNUNET_CONTAINER_multipeermap_get(friend_peers,next_hop);
1312       
1313       if (friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1314       {
1315         GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1316                                 1, GNUNET_NO);
1317       }
1318       /* Send trail setup result message to next hop friend. */
1319       /*FIXME:
1320        I have not yet written the code to copy struct trail message to
1321        pending message. Also, before sending the message I need to check
1322        the MAXIMUM_PENDNIG_PEER limit is not crossed. Modify the same part
1323        of code for handle_dht_p2p_trail_setup. */
1324       pending = GNUNET_malloc (sizeof (struct P2PPendingMessage));
1325       trail_result = (struct PeerTrailSetupResultMessage *) &pending[1];
1326       pending->msg = &trail_result->header;
1327       GNUNET_CONTAINER_DLL_insert_tail (friend->head, friend->tail, pending);
1328       friend->pending_count++;
1329       process_friend_queue(friend);
1330       
1331       return GNUNET_YES;
1332     }
1333   }    
1334   else
1335     return GNUNET_SYSERR;
1336 }
1337
1338
1339 /**
1340  * Initialize neighbours subsystem.
1341  * @return GNUNET_OK on success, GNUNET_SYSERR on error
1342  */
1343 int
1344 GDS_NEIGHBOURS_init()
1345 {
1346   static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1347     {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0},
1348     {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0},
1349     {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0},
1350     {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0},
1351     {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0},
1352     {NULL, 0, 0}
1353   };
1354
1355   /*ASK: What is ATS? Why do we need it? */
1356   atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL);
1357   core_api =
1358     GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
1359                            &handle_core_disconnect, NULL, GNUNET_NO, NULL,
1360                            GNUNET_NO, core_handlers);
1361   if (core_api == NULL)
1362     return GNUNET_SYSERR;
1363
1364   friend_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1365   finger_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
1366   
1367   return GNUNET_OK;
1368 }
1369
1370
1371 /**
1372  * Shutdown neighbours subsystem.
1373  */
1374 void
1375 GDS_NEIGHBOURS_done ()
1376 {
1377   if (NULL == core_api)
1378     return;
1379   GNUNET_CORE_disconnect (core_api);
1380   core_api = NULL;
1381   GNUNET_ATS_performance_done (atsAPI);
1382   atsAPI = NULL;
1383
1384   GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peers));
1385   GNUNET_CONTAINER_multipeermap_destroy (friend_peers);
1386   friend_peers = NULL;
1387
1388   GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peers));
1389   GNUNET_CONTAINER_multipeermap_destroy (finger_peers);
1390   finger_peers = NULL;
1391
1392   if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task)
1393   {
1394     GNUNET_SCHEDULER_cancel (find_finger_trail_task);
1395     find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK;
1396   }
1397 }
1398
1399
1400 /**
1401  * Get the ID of the local node.
1402  *
1403  * @return identity of the local node
1404  */
1405 struct GNUNET_PeerIdentity *
1406 GDS_NEIGHBOURS_get_id ()
1407 {
1408   return &my_identity;
1409 }
1410
1411
1412 /* end of gnunet-service-xdht_neighbours.c */