X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fdht%2Fgnunet-service-xdht_neighbours.c;h=6f3137f8a4b47d90b4191757558930ae7f27b29b;hb=3b680a20ab2cbb98cfa658d85be7a44baaf95d2c;hp=d5139ca73c6a46801fdfc84b31419a35f25ed581;hpb=b046370d179073ed9a3a5ee2eb61269a5178767a;p=oweals%2Fgnunet.git diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c index d5139ca73..6f3137f8a 100644 --- a/src/dht/gnunet-service-xdht_neighbours.c +++ b/src/dht/gnunet-service-xdht_neighbours.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009-2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2009-2014 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -41,7 +41,6 @@ #include "gnunet-service-xdht_datacache.h" #include "gnunet-service-xdht_neighbours.h" #include "gnunet-service-xdht_routing.h" -#include #include "dht.h" /** @@ -52,6 +51,8 @@ * hashing. */ +#define DEBUG(...) \ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Maximum possible fingers (including predecessor) of a peer @@ -71,12 +72,22 @@ /** * How long to wait before sending another verify successor message. */ -#define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1) +#define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) + +/** + * How long to wait before sending another verify successor message. + */ +#define DHT_SEND_VERIFY_SUCCESSOR_RETRY_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) + +/** + * How long to wait before retrying notify successor. + */ +#define DHT_SEND_NOTIFY_SUCCESSOR_RETRY_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) /** * How long at most to wait for transmission of a request to a friend ? */ -#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) +#define PENDING_MESSAGE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) /** * Duration for which I may remain congested. @@ -85,6 +96,12 @@ */ #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) +/** + * In case we don't hear back from the current successor, then we can start + * verify successor. + */ +#define WAIT_NOTIFY_CONFIRMATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) + /** * Maximum number of trails allowed to go through a friend. */ @@ -93,18 +110,13 @@ /** * Maximum number of trails stored per finger. */ -#define MAXIMUM_TRAILS_PER_FINGER 1 +#define MAXIMUM_TRAILS_PER_FINGER 4 /** * Finger map index for predecessor entry in finger table. */ #define PREDECESSOR_FINGER_ID 64 -/** - * Wrap around in peer identity circle. - */ -#define PEER_IDENTITES_WRAP_AROUND pow(2, 64) - 1 - /** * FIXME: Its use only at 3 places check if you can remove it. * To check if a finger is predecessor or not. @@ -272,7 +284,7 @@ struct PeerGetResultMessage /** * When does the content expire? */ - struct GNUNET_TIME_Absolute expiration_time; + struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key of the corresponding GET request. @@ -490,31 +502,24 @@ struct PeerNotifyNewSuccessorMessage }; /** - * P2P Trail Compression Message. + * P2P Notify Successor Confirmation message. */ -struct PeerTrailCompressionMessage +struct PeerNotifyConfirmationMessage { - /** - * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION + /** + * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN */ struct GNUNET_MessageHeader header; /** - * Source peer of this trail. - */ - struct GNUNET_PeerIdentity source_peer; - - /** - * Trail from source_peer to destination_peer compressed such that - * new_first_friend is the first hop in the trail from source to - * destination. + * Unique identifier of the trail. */ - struct GNUNET_PeerIdentity new_first_friend; + struct GNUNET_HashCode trail_id; /** - * Unique identifier of trail. + * Direction of trail. */ - struct GNUNET_HashCode trail_id; + uint32_t trail_direction; }; @@ -617,6 +622,7 @@ struct PeerAddTrailMessage */ }; + GNUNET_NETWORK_STRUCT_END /** @@ -679,6 +685,8 @@ struct FriendInfo */ struct GNUNET_TIME_Absolute congestion_timestamp; + + // TODO : Change name of head and tail to pending_messages_list_head and so. /** * Head of pending messages to be sent to this friend. */ @@ -758,6 +766,12 @@ struct FingerInfo */ struct GNUNET_PeerIdentity finger_identity; + /** + * In case not 0, this amount is time to wait for notify successor message. + * Used ONLY for successor. NOT for any other finger. + */ + struct GNUNET_TIME_Absolute wait_notify_confirmation; + /** * Is any finger stored at this finger index. */ @@ -815,41 +829,49 @@ struct Closest_Peer * to reach to it. In other case, same as best_known_destination. */ struct GNUNET_PeerIdentity next_hop; -}; + /** + * In case finger is the next hop, it contains a valid finger table index + * at which the finger is stored. Else, It contains 65, which is out of range + * of finger table index. + */ + unsigned int finger_table_index; +}; /** - * Data structure to store the trail chosen to reach to finger. + * Context for send_verify_successor_task. */ -struct Selected_Finger_Trail +struct VerifySuccessorContext { /** - * First friend in the trail to reach finger. - */ - struct FriendInfo friend; - - /** - * Identifier of this trail. - */ - struct GNUNET_HashCode trail_id; - - /** - * Total number of peers in this trail. + * Number of times this has been scheduled. */ - unsigned int trail_length; + unsigned int num_retries_scheduled; }; /** * Task that sends FIND FINGER TRAIL requests. This task is started when we have * get our first friend. */ -static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task; +static struct GNUNET_SCHEDULER_Task * find_finger_trail_task; + +/** + * Task that sends verify successor message. This task is started when we get + * our successor for the first time. + */ +static struct GNUNET_SCHEDULER_Task * send_verify_successor_task; /** * Task that sends verify successor message. This task is started when we get * our successor for the first time. */ -static GNUNET_SCHEDULER_TaskIdentifier send_verify_successor_task; +static struct GNUNET_SCHEDULER_Task * send_verify_successor_retry_task; + +/** + * Task that sends verify successor message. This task is started when we get + * our successor for the first time. + */ +static struct GNUNET_SCHEDULER_Task * send_notify_new_successor_retry_task; /** * Identity of this peer. @@ -874,7 +896,7 @@ static struct GNUNET_CORE_Handle *core_api; /** * Handle for the statistics service. */ -extern struct GNUNET_STATISTICS_Handle *GDS_stats; +//extern struct GNUNET_STATISTICS_Handle *GDS_stats; /** * The current finger index that we have want to find trail to. We start the @@ -884,11 +906,59 @@ extern struct GNUNET_STATISTICS_Handle *GDS_stats; */ static unsigned int current_search_finger_index; +/** + * Time duration to schedule find finger trail task. + */ +static struct GNUNET_TIME_Relative find_finger_trail_task_next_send_time; + +/** + * Time duration to schedule verify successor task. + */ +static struct GNUNET_TIME_Relative verify_successor_next_send_time; + +/** + * Time duration to send verify successor again, if result was not received in time. + */ +static struct GNUNET_TIME_Relative verify_successor_retry_time; + +/** + * Time duration to retry send_notify_successor. + */ +static struct GNUNET_TIME_Relative notify_successor_retry_time; + +/** + * Are we waiting for confirmation from our new successor that it got the + * message + */ +//static unsigned int waiting_for_notify_confirmation; + +/* Below variables are used only for testing, and statistics collection. */ /** * Should we store our topology predecessor and successor IDs into statistics? */ unsigned int track_topology; +/** + * Should I be a malicious peer and drop the PUT/GET packets? + * if 0 then NOT malicious. + */ +unsigned int act_malicious; + +/** + * Count of fingers found. Ideally we should have O(logn) fingers for a + * stable network. + */ +static unsigned int total_fingers_found; + +/** + * Number of times we found the same successor. + */ +static unsigned int successor_times; + +/** + * Number of rounds for which we should search for finger. + */ +static unsigned int fingers_round_count; /** * Called when core is ready to send a message we asked for * out to the destination. @@ -908,11 +978,18 @@ core_transmit_notify (void *cls, size_t size, void *buf) size_t msize; peer->th = NULL; - while ((NULL != (pending = peer->head)) && - (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us)) + while ( (NULL != (pending = peer->head)) && + (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us) ) { + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Messages dropped (CORE timeout)"), + 1, + GNUNET_NO); peer->pending_count--; - GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending); + GNUNET_CONTAINER_DLL_remove (peer->head, + peer->tail, + pending); GNUNET_free (pending); } if (NULL == pending) @@ -936,10 +1013,11 @@ core_transmit_notify (void *cls, size_t size, void *buf) while ((NULL != (pending = peer->head)) && (size - off >= (msize = ntohs (pending->msg->size)))) { - /*GNUNET_STATISTICS_update (GDS_stats, + GNUNET_STATISTICS_update (GDS_stats, gettext_noop - ("# Bytes transmitted to other peers"), msize, - GNUNET_NO);*/ + ("# Bytes transmitted to other peers"), + msize, + GNUNET_NO); memcpy (&cbuf[off], pending->msg, msize); off += msize; peer->pending_count--; @@ -978,10 +1056,6 @@ process_friend_queue (struct FriendInfo *peer) { return; } - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop - ("# Bytes of bandwidth requested from core"), - ntohs (pending->msg->size), GNUNET_NO); peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, @@ -994,6 +1068,19 @@ process_friend_queue (struct FriendInfo *peer) } +#if ENABLE_MALICIOUS +/** + * Set the ENABLE_MALICIOUS value to malicious. + * @param malicious + */ +int +GDS_NEIGHBOURS_act_malicious (unsigned int malicious) +{ + act_malicious = malicious; + return GNUNET_OK; +} +#endif + /** * Construct a trail setup message and forward it to target_friend * @param source_peer Peer which wants to setup the trail @@ -1030,7 +1117,7 @@ GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer, msize = sizeof (struct PeerTrailSetupMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1041,11 +1128,10 @@ GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer, GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); } - pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); tsm = (struct PeerTrailSetupMessage *) &pending[1]; - pending->msg = &tsm->header; + pending->msg = &(tsm->header); tsm->header.size = htons (msize); tsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP); tsm->final_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value); @@ -1099,7 +1185,7 @@ GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer msize = sizeof (struct PeerTrailSetupResultMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1114,7 +1200,7 @@ GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); tsrm = (struct PeerTrailSetupResultMessage *) &pending[1]; pending->msg = &tsrm->header; tsrm->header.size = htons (msize); @@ -1126,7 +1212,6 @@ GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer tsrm->ulitmate_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value); peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1]; - memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ @@ -1135,6 +1220,50 @@ GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer process_friend_queue (target_friend); } +/** + * Send notify successor confirmation message. + * @param trail_id Unique Identifier of the trail. + * @param trail_direction Destination to Source. + * @param target_friend Friend to get this message next. + */ +void +GDS_NEIGHBOURS_send_notify_succcessor_confirmation (struct GNUNET_HashCode trail_id, + unsigned int trail_direction, + struct FriendInfo *target_friend) +{ + struct PeerNotifyConfirmationMessage *ncm; + struct P2PPendingMessage *pending; + size_t msize; + + msize = sizeof (struct PeerNotifyConfirmationMessage); + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) + { + GNUNET_break (0); + return; + } + + if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) + { + GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), + 1, GNUNET_NO); + } + + pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); + pending->importance = 0; /* FIXME */ + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); + ncm = (struct PeerNotifyConfirmationMessage *) &pending[1]; + pending->msg = &ncm->header; + ncm->header.size = htons (msize); + ncm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION); + ncm->trail_id = trail_id; + ncm->trail_direction = htonl (trail_direction); + + /* Send the message to chosen friend. */ + GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); + target_friend->pending_count++; + process_friend_queue (target_friend); +} + /** * Send trail rejection message to target friend @@ -1171,7 +1300,7 @@ GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer, msize = sizeof (struct PeerTrailRejectionMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1185,7 +1314,7 @@ GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer, pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); trm = (struct PeerTrailRejectionMessage *)&pending[1]; pending->msg = &trm->header; trm->header.size = htons (msize); @@ -1236,8 +1365,9 @@ GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_ size_t msize; msize = sizeof (struct PeerVerifySuccessorMessage) + - (trail_length * sizeof (struct GNUNET_PeerIdentity));; - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); + + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1251,7 +1381,7 @@ GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_ pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); vsm = (struct PeerVerifySuccessorMessage *) &pending[1]; pending->msg = &vsm->header; vsm->header.size = htons (msize); @@ -1259,12 +1389,8 @@ GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_ vsm->source_peer = source_peer; vsm->successor = successor; vsm->trail_id = trail_id; - - if (trail_length != 0) - { - peer_list = (struct GNUNET_PeerIdentity *) &vsm[1]; - memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity)); - } + peer_list = (struct GNUNET_PeerIdentity *) &vsm[1]; + memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); @@ -1279,14 +1405,15 @@ GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_ * the pointer to friend in routing table rather than gnunet_peeridentity. * if yes then we should keep friend info in.h andmake lot of changes. * Construct a trail teardown message and forward it to target friend. + * * @param trail_id Unique identifier of the trail. * @param trail_direction Direction of trail. * @param target_friend Friend to get this message. */ void -GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id, +GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_HashCode *trail_id, unsigned int trail_direction, - struct GNUNET_PeerIdentity peer) + const struct GNUNET_PeerIdentity *peer) { struct PeerTrailTearDownMessage *ttdm; struct P2PPendingMessage *pending; @@ -1294,17 +1421,19 @@ GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id, size_t msize; msize = sizeof (struct PeerTrailTearDownMessage); - - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; } - /*FIXME:In what case friend can be null. ?*/ if (NULL == (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, &peer))); - return; + GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))) + { + /* FIXME: In what case friend can be null. ?*/ + GNUNET_break (0); + return; + } if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) { @@ -1314,12 +1443,12 @@ GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id, pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); ttdm = (struct PeerTrailTearDownMessage *) &pending[1]; pending->msg = &ttdm->header; ttdm->header.size = htons (msize); ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN); - ttdm->trail_id = trail_id; + ttdm->trail_id = *trail_id; ttdm->trail_direction = htonl (trail_direction); /* Send the message to chosen friend. */ @@ -1362,7 +1491,7 @@ GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying msize = sizeof (struct PeerVerifySuccessorResultMessage) + (trail_length * sizeof(struct GNUNET_PeerIdentity)); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1376,7 +1505,7 @@ GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1]; pending->msg = &vsmr->header; vsmr->header.size = htons (msize); @@ -1386,12 +1515,8 @@ GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying vsmr->probable_successor = probable_successor; vsmr->trail_direction = htonl (trail_direction); vsmr->trail_id = trail_id; - - if (trail_length > 0) - { - peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1]; - memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity)); - } + peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1]; + memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); @@ -1428,7 +1553,7 @@ GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer msize = sizeof (struct PeerNotifyNewSuccessorMessage) + (successor_trail_length * sizeof(struct GNUNET_PeerIdentity)); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1442,7 +1567,7 @@ GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1]; pending->msg = &nsm->header; nsm->header.size = htons (msize); @@ -1450,13 +1575,9 @@ GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer nsm->new_successor = successor; nsm->source_peer = source_peer; nsm->trail_id = succesor_trail_id; - - if (successor_trail_length > 0) - { - peer_list = (struct GNUNET_PeerIdentity *) &nsm[1]; - memcpy (peer_list, successor_trail, - successor_trail_length * sizeof (struct GNUNET_PeerIdentity)); - } + peer_list = (struct GNUNET_PeerIdentity *) &nsm[1]; + memcpy (peer_list, successor_trail, + successor_trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); @@ -1492,7 +1613,7 @@ GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer, msize = sizeof (struct PeerAddTrailMessage) + (trail_length * sizeof(struct GNUNET_PeerIdentity)); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; @@ -1506,7 +1627,7 @@ GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer, pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); adm = (struct PeerAddTrailMessage *) &pending[1]; pending->msg = &adm->header; adm->header.size = htons (msize); @@ -1516,58 +1637,8 @@ GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer, adm->trail_id = trail_id; peer_list = (struct GNUNET_PeerIdentity *)&adm[1]; memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length); - - /* Send the message to chosen friend. */ - GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); - target_friend->pending_count++; - process_friend_queue (target_friend); - -} - - -/** - * Construct a trail compression message and send it to target_friend. - * @param source_peer Source of the trail. - * @param trail_id Unique identifier of trail. - * @param first_friend First hop in compressed trail to reach from source to finger - * @param target_friend Next friend to get this message. - */ -void -GDS_NEIGHBOURS_send_trail_compression (struct GNUNET_PeerIdentity source_peer, - struct GNUNET_HashCode trail_id, - struct GNUNET_PeerIdentity first_friend, - struct FriendInfo *target_friend) -{ - struct P2PPendingMessage *pending; - struct PeerTrailCompressionMessage *tcm; - size_t msize; - - msize = sizeof (struct PeerTrailCompressionMessage); - - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) - { - GNUNET_break (0); - return; - } - - if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) - { - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop ("# P2P messages dropped due to full queue"), - 1, GNUNET_NO); - } - - pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); - pending->importance = 0; /* FIXME */ - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); - tcm = (struct PeerTrailCompressionMessage *) &pending[1]; - pending->msg = &tcm->header; - tcm->header.size = htons (msize); - tcm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION); - tcm->source_peer = source_peer; - tcm->new_first_friend = first_friend; - tcm->trail_id = trail_id; + /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); @@ -1580,6 +1651,7 @@ GDS_NEIGHBOURS_send_trail_compression (struct GNUNET_PeerIdentity source_peer, * trail (can happen during trail setup), then return my lowest index. * @param trail List of peers * @return my_index if found + * trail_length + 1 if an entry is present twice, It is an error. * -1 if no entry found. */ static int @@ -1587,14 +1659,28 @@ search_my_index (const struct GNUNET_PeerIdentity *trail, int trail_length) { int i; + int index_seen = trail_length + 1; + int flag = 0; for (i = 0; i < trail_length; i++) { if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i])) - return i; + { + flag = 1; + if(index_seen == (trail_length + 1)) + index_seen = i; + else + { + DEBUG("Entry is present twice in trail. Its not allowed\n"); + } + break; + } } - return -1; + if (1 == flag) + return index_seen; + else + return -1; } @@ -1608,7 +1694,7 @@ search_my_index (const struct GNUNET_PeerIdentity *trail, static int is_friend_congested (struct FriendInfo *friend) { - if ((TRAILS_THROUGH_FRIEND_THRESHOLD > friend->trails_count) && + if (( friend->trails_count < TRAILS_THROUGH_FRIEND_THRESHOLD) && ((0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_timestamp).rel_value_us))) return GNUNET_NO; @@ -1624,7 +1710,7 @@ is_friend_congested (struct FriendInfo *friend) * @param value Value to be compare * @return Closest peer */ -const static struct GNUNET_PeerIdentity * +static struct GNUNET_PeerIdentity select_closest_finger (const struct GNUNET_PeerIdentity *peer1, const struct GNUNET_PeerIdentity *peer2, uint64_t value) @@ -1639,40 +1725,38 @@ select_closest_finger (const struct GNUNET_PeerIdentity *peer1, if (peer1_value == value) { - return peer1; + return *peer1; } if (peer2_value == value) { - return peer2; + return *peer2; } - if (peer2_value < peer1_value) + if (value < peer1_value && peer1_value < peer2_value) { - if ((peer2_value < value) && (value < peer1_value)) - { - return peer1; - } - else if (((peer1_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) || - ((0 < value) && (value < peer2_value))) - { - return peer2; - } + return *peer1; } - - if (peer1_value < peer2_value) + else if (value < peer2_value && peer2_value < peer1_value) { - if ((peer1_value < value) && (value < peer2_value)) - { - return peer2; - } - else if (((peer2_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) || - ((0 < value) && (value < peer1_value))) - { - return peer1; - } + return *peer2; + } + else if (peer1_value < value && value < peer2_value) + { + return *peer2; + } + else if (peer2_value < value && value < peer1_value) + { + return *peer1; + } + else if (peer1_value < peer2_value && peer2_value < value) + { + return *peer1; + } + else // if (peer2_value < peer1_value && peer1_value < value) + { + return *peer2; } - return NULL; } @@ -1683,7 +1767,7 @@ select_closest_finger (const struct GNUNET_PeerIdentity *peer1, * @param value Value to be compare * @return Peer which precedes value in the network. */ -const static struct GNUNET_PeerIdentity * +static struct GNUNET_PeerIdentity select_closest_predecessor (const struct GNUNET_PeerIdentity *peer1, const struct GNUNET_PeerIdentity *peer2, uint64_t value) @@ -1696,39 +1780,64 @@ select_closest_predecessor (const struct GNUNET_PeerIdentity *peer1, peer1_value = GNUNET_ntohll (peer1_value); peer2_value = GNUNET_ntohll (peer2_value); - if (peer1_value == value) - return peer1; + if (peer1_value == value) + { + return *peer1; + } if (peer2_value == value) - return peer2; + { + return *peer2; + } - if (peer1_value < peer2_value) + if (value < peer1_value && peer1_value < peer2_value) { - if ((peer1_value < value) && (value < peer2_value)) - { - return peer1; - } - else if (((peer2_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) || - ((PEER_IDENTITES_WRAP_AROUND > value) && (value < peer1_value))) - { - return peer2; - } + return *peer2; + } + else if (value < peer2_value && peer2_value < peer1_value) + { + return *peer1; + } + else if (peer1_value < value && value < peer2_value) + { + return *peer1; + } + else if (peer2_value < value && value < peer1_value) + { + return *peer2; + } + else if (peer1_value < peer2_value && peer2_value < value) + { + return *peer2; + } + else // if (peer2_value < peer1_value && peer1_value < value) + { + return *peer1; } +} + +#if 0 +/** + * + * + */ +void +test_print_trail (struct GNUNET_PeerIdentity *trail, + unsigned int trail_length) +{ + struct GNUNET_PeerIdentity print_peer; + int i; - if (peer2_value < peer1_value) + FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail_length = %d"), + __FILE__, __func__,__LINE__,trail_length); + for (i =0 ; i< trail_length; i++) { - if ((peer2_value < value) && (value < peer1_value)) - { - return peer2; - } - else if (((peer1_value < value) && (value < PEER_IDENTITES_WRAP_AROUND)) || - ((PEER_IDENTITES_WRAP_AROUND > value) && (value < peer2_value))) - { - return peer1; - } + print_peer = trail[i]; + FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail[%d]=%s"), + __FILE__, __func__,__LINE__,i,GNUNET_i2s(&print_peer)); } - return NULL; } +#endif #if 0 /** @@ -1759,9 +1868,9 @@ test_friend_peermap_print () } } } +#endif - - +#if 0 /** * This is a test function, to print all the entries of finger table. */ @@ -1816,15 +1925,19 @@ test_finger_table_print() * @param is_predecessor Is value a predecessor or any other finger. * @return Closest peer among two peers. */ -const static struct GNUNET_PeerIdentity * +static struct GNUNET_PeerIdentity select_closest_peer (const struct GNUNET_PeerIdentity *peer1, const struct GNUNET_PeerIdentity *peer2, uint64_t value, unsigned int is_predecessor) { + /* This check is here to ensure that calling function never sends + same peer value in peer1 and peer2. Remove it later. */ + GNUNET_assert(0 != GNUNET_CRYPTO_cmp_peer_identity (peer1, peer2)); if (1 == is_predecessor) return select_closest_predecessor (peer1, peer2, value); + // TODO: Change name to something like select_closest_successor!! return select_closest_finger (peer1, peer2, value); } @@ -1836,64 +1949,43 @@ select_closest_peer (const struct GNUNET_PeerIdentity *peer1, * to Finger, choose the one with shortest trail length. * Note: We use length as parameter. But we can use any other suitable parameter * also. - * @param finger Finger - * @return struct Selected_Finger_Trail which contains the first friend , trail id - * and trail length. NULL in case none of the trails are free. + * @param finger Finger Finger whose trail we have to select. + * @return Trail Selected Trail. */ -static struct Selected_Finger_Trail * +static struct Trail * select_finger_trail (struct FingerInfo *finger) { struct FriendInfo *friend; - struct Trail *iterator; - struct Selected_Finger_Trail *finger_trail; + struct Trail *current_finger_trail; + struct Trail *best_trail = NULL; unsigned int i; - unsigned int flag = 0; - unsigned int j = 0; - finger_trail = GNUNET_new (struct Selected_Finger_Trail); GNUNET_assert (finger->trails_count > 0); - for (i = 0; i < finger->trails_count; i++) { - iterator = &finger->trail_list[i]; + current_finger_trail = &finger->trail_list[i]; /* No trail stored at this index. */ - if (GNUNET_NO == iterator->is_present) + if (GNUNET_NO == current_finger_trail->is_present) continue; GNUNET_assert (NULL != (friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &iterator->trail_head->peer))); + ¤t_finger_trail->trail_head->peer))); /* First friend to reach trail is not free. */ if (GNUNET_YES == is_friend_congested (friend)) - { - j++; continue; - } - if (!flag) - { - flag = 1; - finger_trail->trail_length = iterator->trail_length; - finger_trail->friend = *friend; - finger_trail->trail_id = iterator->trail_id; - } - else if (finger_trail->trail_length > iterator->trail_length) + if (NULL == best_trail || + best_trail->trail_length > current_finger_trail->trail_length) { - finger_trail->friend = *friend; - finger_trail->trail_id = iterator->trail_id; - finger_trail->trail_length = iterator->trail_length; + best_trail = current_finger_trail; } } - /* All the first friend in all the trails to reach to finger are either - congested or have crossed trail threshold. */ - if (j == finger->trails_count) - return NULL; - - return finger_trail; + return best_trail; } @@ -1906,11 +1998,11 @@ select_finger_trail (struct FingerInfo *finger) * @return */ static void -compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer) +compare_finger_and_current_closest_peer (struct Closest_Peer *current_closest_peer) { struct FingerInfo *finger; - const struct GNUNET_PeerIdentity *closest_peer; - struct Selected_Finger_Trail *finger_trail; + struct GNUNET_PeerIdentity closest_peer; + struct Trail *finger_trail; int i; /* Iterate over finger table. */ @@ -1921,7 +2013,6 @@ compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer) if (GNUNET_NO == finger->is_present) continue; - /* FIXME write correct comment here */ if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, ¤t_closest_peer->best_known_destination)) continue; @@ -1929,16 +2020,9 @@ compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer) /* If I am my own finger, then ignore this finger. */ if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, &my_identity)) - { - /* FIXME: I think a peer should not select itself as its own identity ever. - But it does select. Find out why??*/ - //GNUNET_break (0); - //continue; - return; - } + continue; - /* If finger is a friend, then do nothing. As we have already checked - * for each friend in compare_friend_and_current_successor(). */ + /* If finger is a friend, we have already checked it in previous function. */ if (NULL != (GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger->finger_identity))) { @@ -1950,7 +2034,7 @@ compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer) current_closest_peer->destination_finger_value, current_closest_peer->is_predecessor); - if (&finger->finger_identity == closest_peer) + if (0 == GNUNET_CRYPTO_cmp_peer_identity(&finger->finger_identity, &closest_peer)) { /* Choose one of the trail to reach to finger. */ finger_trail = select_finger_trail (finger); @@ -1959,10 +2043,10 @@ compare_finger_and_current_successor (struct Closest_Peer *current_closest_peer) if (NULL == finger_trail) continue; - current_closest_peer->best_known_destination = finger->finger_identity; - current_closest_peer->next_hop = finger_trail->friend.id; + current_closest_peer->best_known_destination = closest_peer; + current_closest_peer->next_hop = finger_trail->trail_head->peer; current_closest_peer->trail_id = finger_trail->trail_id; - //GNUNET_free(finger_trail);//FIXME: where should we free the finger trail. + current_closest_peer->finger_table_index = i; } continue; } @@ -1988,7 +2072,7 @@ compare_friend_and_current_closest_peer (void *cls, { struct FriendInfo *friend = value; struct Closest_Peer *current_closest_peer = cls; - const struct GNUNET_PeerIdentity *closest_peer; + struct GNUNET_PeerIdentity closest_peer; /* Friend is either congested or has crossed threshold. */ if (GNUNET_YES == is_friend_congested (friend)) @@ -2008,7 +2092,7 @@ compare_friend_and_current_closest_peer (void *cls, current_closest_peer->is_predecessor); /* Is friend the closest successor? */ - if (&friend->id == closest_peer) + if (0 == GNUNET_CRYPTO_cmp_peer_identity(&friend->id, &closest_peer)) { current_closest_peer->best_known_destination = friend->id; current_closest_peer->next_hop = friend->id; @@ -2024,7 +2108,7 @@ compare_friend_and_current_closest_peer (void *cls, * @return Updated closest_peer */ static struct Closest_Peer -init_current_successor (struct GNUNET_PeerIdentity my_identity, +init_closest_peer (struct GNUNET_PeerIdentity my_identity, uint64_t destination_finger_value, unsigned int is_predecessor) { @@ -2035,36 +2119,32 @@ init_current_successor (struct GNUNET_PeerIdentity my_identity, current_closest_peer.is_predecessor = is_predecessor; current_closest_peer.next_hop = my_identity; current_closest_peer.best_known_destination = my_identity; - + current_closest_peer.finger_table_index = 65; //65 is a for non valid finger table index. return current_closest_peer; } /** - * FIXME: at the moment, there is not 100% get and put in case of non-malicious - * peer. It could be because of the logic we wrote here. Verify if its correct. - * If not then return immediate_successor. + * Find locally best known peer, among your own identity, friend and finger list, + * which is closest to given destination_finger_value. * - * Find the successor for destination_finger_value among my_identity, my - * friends and my fingers. Don't consider friends or fingers which are either - * congested or have crossed the threshold. * NOTE: In case a friend is also a finger, then it is always chosen as friend * not a finger. - * @param destination_finger_value Peer closest to this value will be the next successor. + * @param destination_finger_value Peer closest to this value will be the next destination. * @param is_predecessor Are we looking for predecessor or finger? - * @return Successor It is never NULL, in case none of friend or finger is closest, - * then we return my_identity. + * @return Closest_Peer that contains all the relevant field to reach to + * @a destination_finger_value */ static struct Closest_Peer -find_successor (uint64_t destination_finger_value, - unsigned int is_predecessor) +find_local_best_known_next_hop (uint64_t destination_finger_value, + unsigned int is_predecessor) { struct Closest_Peer current_closest_peer; /* Initialize current_successor to my_identity. */ - current_closest_peer = init_current_successor (my_identity, - destination_finger_value, - is_predecessor); + current_closest_peer = init_closest_peer (my_identity, + destination_finger_value, + is_predecessor); /* Compare each friend entry with current_successor and update current_successor * with friend if its closest. */ @@ -2076,8 +2156,7 @@ find_successor (uint64_t destination_finger_value, /* Compare each finger entry with current_successor and update current_successor * with finger if its closest. */ - compare_finger_and_current_successor (¤t_closest_peer); - + compare_finger_and_current_closest_peer (¤t_closest_peer); return current_closest_peer; } @@ -2102,13 +2181,13 @@ find_successor (uint64_t destination_finger_value, void GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type block_type, - enum GNUNET_DHT_RouteOption options, - uint32_t desired_replication_level, - struct GNUNET_PeerIdentity best_known_dest, - struct GNUNET_HashCode intermediate_trail_id, - struct GNUNET_PeerIdentity *target_peer, - uint32_t hop_count, - uint32_t put_path_length, + enum GNUNET_DHT_RouteOption options, + uint32_t desired_replication_level, + struct GNUNET_PeerIdentity best_known_dest, + struct GNUNET_HashCode intermediate_trail_id, + struct GNUNET_PeerIdentity *target_peer, + uint32_t hop_count, + uint32_t put_path_length, struct GNUNET_PeerIdentity *put_path, struct GNUNET_TIME_Absolute expiration_time, const void *data, size_t data_size) @@ -2117,59 +2196,26 @@ GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key, struct P2PPendingMessage *pending; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *pp; - struct GNUNET_PeerIdentity next_hop; - size_t msize; msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + sizeof (struct PeerPutMessage); - - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { put_path_length = 0; msize = data_size + sizeof (struct PeerPutMessage); } - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { + DEBUG("msize = %lu\n",msize); GNUNET_break (0); return; } - /* This is the first call made from clients file. So, we should search for the - target_friend. */ - if (NULL == target_peer) - { - uint64_t key_value; - struct Closest_Peer successor; - - memcpy (&key_value, key, sizeof (uint64_t)); - key_value = GNUNET_ntohll (key_value); - - successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR); - best_known_dest = successor.best_known_destination; - next_hop = successor.next_hop; - intermediate_trail_id = successor.trail_id; - - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)) - { - /* I am the destination. */ - GDS_DATACACHE_handle_put (expiration_time, key, 0, NULL, - block_type,data_size,data); - return; - } - else - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop))); - } - else - { - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); - } - + GNUNET_assert (NULL != + (target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->timeout = expiration_time; ppm = (struct PeerPutMessage *) &pending[1]; @@ -2180,24 +2226,109 @@ GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key, ppm->block_type = htonl (block_type); ppm->hop_count = htonl (hop_count + 1); ppm->desired_replication_level = htonl (desired_replication_level); - ppm->put_path_length = htonl (put_path_length); ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); ppm->best_known_destination = best_known_dest; + ppm->intermediate_trail_id = intermediate_trail_id; ppm->key = *key; - pp = (struct GNUNET_PeerIdentity *) &ppm[1]; - if (put_path_length != 0) + ppm->put_path_length = htonl (put_path_length); + if(put_path_length > 0) { memcpy (pp, put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length); } memcpy (&pp[put_path_length], data, data_size); + GNUNET_assert (NULL != target_friend); GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } +/** + * Handle the put request from the client. + * @param key Key for the content + * @param block_type Type of the block + * @param options Routing options + * @param desired_replication_level Desired replication count + * @param expiration_time When does the content expire + * @param data Content to store + * @param data_size Size of content @a data in bytes + */ +void +GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key, + enum GNUNET_BLOCK_Type block_type, + enum GNUNET_DHT_RouteOption options, + uint32_t desired_replication_level, + struct GNUNET_TIME_Absolute expiration_time, + const void *data, size_t data_size) +{ + struct GNUNET_PeerIdentity best_known_dest; + struct GNUNET_HashCode intermediate_trail_id; + struct GNUNET_PeerIdentity next_hop; + uint64_t key_value; + struct Closest_Peer successor; + + memcpy (&key_value, key, sizeof (uint64_t)); + key_value = GNUNET_ntohll (key_value); + successor = find_local_best_known_next_hop (key_value, + GDS_FINGER_TYPE_NON_PREDECESSOR); + best_known_dest = successor.best_known_destination; + next_hop = successor.next_hop; + intermediate_trail_id = successor.trail_id; + + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity)) + { + DEBUG("\n PUT_REQUEST_SUCCESSFUL for key = %s",GNUNET_h2s(key)); + /* I am the destination. */ + GDS_DATACACHE_handle_put (expiration_time, key, 0, NULL, + block_type,data_size,data); + GDS_CLIENTS_process_put (options, block_type, 0, + ntohl (desired_replication_level), + 1, &my_identity, expiration_time, //FIXME: GNUNETnthoh something on expiration time. + key, data, data_size); + return; + } + /* In case we are sending the request to a finger, then send across all of its + trail.*/ +#if ENABLE_MALICIOUS + if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination, + &successor.next_hop)) + { + struct FingerInfo *next_hop_finger; + unsigned int i; + + next_hop_finger = &finger_table[successor.finger_table_index]; + for (i = 0; i < next_hop_finger->trails_count; i++) + { + if (GNUNET_YES == next_hop_finger->trail_list[i].is_present) + { + if(0 == next_hop_finger->trail_list[i].trail_length) + { + GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level, + best_known_dest, intermediate_trail_id, &next_hop, + 0, 1, &my_identity, expiration_time, + data, data_size); + return; + } + next_hop = next_hop_finger->trail_list[i].trail_head->peer; + GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level, + best_known_dest, + next_hop_finger->trail_list[i].trail_id, + &next_hop, 0, 1, &my_identity, + expiration_time, + data, data_size); + } + } + return; + } +#endif + GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level, + best_known_dest, intermediate_trail_id, &next_hop, + 0, 1, &my_identity, expiration_time, + data, data_size); +} + /** * Construct a Get message and send it to target_peer. * @param key Key for the content @@ -2236,54 +2367,17 @@ GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key, msize = sizeof (struct PeerGetMessage) + (get_path_length * sizeof (struct GNUNET_PeerIdentity)); - /* In this case we don't make get_path_length = 0, as we need get path to - * return the message back to querying client. */ - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return; } - - /* This is the first time we got request from our own client file. */ - if (NULL == target_peer) - { - uint64_t key_value; - struct Closest_Peer successor; - - memcpy (&key_value, key, sizeof (uint64_t)); - key_value = GNUNET_ntohll (key_value); - successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR); - - best_known_dest = successor.best_known_destination; - intermediate_trail_id = successor.trail_id; - - /* I am the destination. I have the data. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, - &best_known_dest)) - { - GDS_DATACACHE_handle_get (key,block_type, NULL, 0, - NULL, 0, 1, &my_identity, NULL,&my_identity); - - return; - } - else - { - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &successor.next_hop))); - } - - } - else - { - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); //FIXME: assertion fails. - } + GNUNET_assert (NULL != + (target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); pending->importance = 0; /* FIXME */ pgm = (struct PeerGetMessage *) &pending[1]; pending->msg = &pgm->header; @@ -2294,21 +2388,95 @@ GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key, pgm->key = *key; pgm->intermediate_trail_id = intermediate_trail_id; pgm->hop_count = htonl (hop_count + 1); + pgm->get_path_length = htonl (get_path_length); gp = (struct GNUNET_PeerIdentity *) &pgm[1]; + memcpy (gp, get_path, + sizeof (struct GNUNET_PeerIdentity) * get_path_length); + GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); + target_friend->pending_count++; + process_friend_queue (target_friend); +} + + +/** + * Handle the get request from the client file. If I am destination do + * datacache put and return. Else find the target friend and forward message + * to it. + * @param key Key for the content + * @param block_type Type of the block + * @param options Routing options + * @param desired_replication_level Desired replication count + */ +void +GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key, + enum GNUNET_BLOCK_Type block_type, + enum GNUNET_DHT_RouteOption options, + uint32_t desired_replication_level) +{ + struct Closest_Peer successor; + struct GNUNET_PeerIdentity best_known_dest; + struct GNUNET_HashCode intermediate_trail_id; + uint64_t key_value; + + memcpy (&key_value, key, sizeof (uint64_t)); + key_value = GNUNET_ntohll (key_value); + + successor = find_local_best_known_next_hop (key_value, + GDS_FINGER_TYPE_NON_PREDECESSOR); - if (get_path_length != 0) + best_known_dest = successor.best_known_destination; + intermediate_trail_id = successor.trail_id; + + /* I am the destination. I have the data. */ + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, + &best_known_dest)) { - memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); + GDS_DATACACHE_handle_get (key,block_type, NULL, 0, + NULL, 0, 1, &my_identity, NULL,&my_identity); + return; } - GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); - target_friend->pending_count++; - process_friend_queue (target_friend); +#if ENABLE_MALICIOUS + struct GNUNET_PeerIdentity next_hop; + if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination, + &successor.next_hop)) + { + struct FingerInfo *next_hop_finger; + unsigned int i; + + next_hop_finger = &finger_table[successor.finger_table_index]; + for (i = 0; i < next_hop_finger->trails_count; i++) + { + if (GNUNET_YES == next_hop_finger->trail_list[i].is_present) + { + if(0 == next_hop_finger->trail_list[i].trail_length) + { + GDS_NEIGHBOURS_send_get (key, block_type, options, + desired_replication_level, + best_known_dest,intermediate_trail_id, + &successor.next_hop, + 0, 1, &my_identity); + return; + } + next_hop = next_hop_finger->trail_list[i].trail_head->peer; + GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level, + best_known_dest, + next_hop_finger->trail_list[i].trail_id, + &next_hop, 0, 1, &my_identity); + } + } + return; + } +#endif + GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level, + best_known_dest,intermediate_trail_id, &successor.next_hop, + 0, 1, &my_identity); } /** * Send the get result to requesting client. + * * @param key Key of the requested data. * @param type Block type * @param target_peer Next peer to forward the message to. @@ -2344,12 +2512,17 @@ GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key, data_size + sizeof (struct PeerGetResultMessage); - if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { - GNUNET_break (0); - return; + put_path_length = 0; + msize = msize - put_path_length * sizeof (struct GNUNET_PeerIdentity); } + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) + { + GNUNET_break(0); + return; + } current_path_index = 0; if(get_path_length > 0) { @@ -2359,9 +2532,16 @@ GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key, GNUNET_break (0); return; } + if ((get_path_length + 1) == current_path_index) + { + DEBUG ("Peer found twice in get path. Not allowed \n"); + GNUNET_break (0); + return; + } } if (0 == current_path_index) { + DEBUG ("GET_RESULT TO CLIENT KEY = %s, Peer = %s",GNUNET_h2s(key),GNUNET_i2s(&my_identity)); GDS_CLIENTS_handle_reply (expiration, key, get_path_length, get_path, put_path_length, put_path, type, data_size, data); @@ -2369,7 +2549,7 @@ GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key, } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); - pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); + pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); pending->importance = 0; get_result = (struct PeerGetResultMessage *)&pending[1]; pending->msg = &get_result->header; @@ -2377,7 +2557,7 @@ GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key, get_result->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT); get_result->key = *key; get_result->querying_peer = *source_peer; - get_result->expiration_time = expiration; + get_result->expiration_time = GNUNET_TIME_absolute_hton (expiration); get_result->get_path_length = htonl (get_path_length); get_result->put_path_length = htonl (put_path_length); paths = (struct GNUNET_PeerIdentity *)&get_result[1]; @@ -2427,6 +2607,7 @@ select_random_friend () for (j = 0; j < index ; j++) GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); + do { /* Reset the index in friend peermap to 0 as we reached to the end. */ @@ -2445,7 +2626,7 @@ select_random_friend () (const void **)&friend)); /* This friend is not congested and has not crossed trail threshold. */ - if ((TRAILS_THROUGH_FRIEND_THRESHOLD > friend->trails_count) && + if ((friend->trails_count < TRAILS_THROUGH_FRIEND_THRESHOLD) && (0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_timestamp).rel_value_us)) { break; @@ -2486,7 +2667,6 @@ compute_finger_identity_value (unsigned int finger_index) } } -static struct GNUNET_TIME_Relative next_send_time; /* * Choose a random friend. Calculate the next finger identity to search,from @@ -2494,31 +2674,32 @@ static struct GNUNET_TIME_Relative next_send_time; * finger identity through this random friend. * * @param cls closure for this task - * @param tc the context under which the task is running */ static void -send_find_finger_trail_message (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +send_find_finger_trail_message (void *cls) { struct FriendInfo *target_friend; - //struct GNUNET_TIME_Relative next_send_time; struct GNUNET_HashCode trail_id; struct GNUNET_HashCode intermediate_trail_id; - unsigned int is_predecessor; + unsigned int is_predecessor = 0; uint64_t finger_id_value; - - /* Schedule another send_find_finger_trail_message task. */ + + /* Schedule another send_find_finger_trail_message task. After one round of + * finger search, this time is exponentially backoff. */ + find_finger_trail_task_next_send_time.rel_value_us = + find_finger_trail_task_next_send_time.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us); find_finger_trail_task = - GNUNET_SCHEDULER_add_delayed (next_send_time, + GNUNET_SCHEDULER_add_delayed (find_finger_trail_task_next_send_time, &send_find_finger_trail_message, NULL); - /* No space in my routing table. (Source and destination peers also store entries + /* No space in my routing table. (Source and destination peers also store entries * in their routing table). */ if (GNUNET_YES == GDS_ROUTING_threshold_reached()) return; - target_friend = select_random_friend (); if (NULL == target_friend) { @@ -2526,17 +2707,13 @@ send_find_finger_trail_message (void *cls, } finger_id_value = compute_finger_identity_value (current_search_finger_index); - if (PREDECESSOR_FINGER_ID == current_search_finger_index) is_predecessor = 1; - else - is_predecessor = 0; /* Generate a unique trail id for trail we are trying to setup. */ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, &trail_id, sizeof (trail_id)); memset(&intermediate_trail_id, 0, sizeof (struct GNUNET_HashCode)); - GDS_NEIGHBOURS_send_trail_setup (my_identity, finger_id_value, target_friend->id, target_friend, 0, NULL, is_predecessor, trail_id, @@ -2556,34 +2733,37 @@ send_find_finger_trail_message (void *cls, * 2. if the new trail is completely disjoint than the * other trails, then may be choosing it is better. * - * @param existing_finger - * @param new_finger_trail - * @param new_finger_trail_length - * @param new_finger_trail_id + * @param finger Finger + * @param new_finger_trail List of peers to reach from me to @a finger, NOT + * including the endpoints. + * @param new_finger_trail_length Total number of peers in @a new_finger_trail + * @param new_finger_trail_id Unique identifier of @a new_finger_trail. */ static void -select_and_replace_trail (struct FingerInfo *existing_finger, +select_and_replace_trail (struct FingerInfo *finger, const struct GNUNET_PeerIdentity *new_trail, unsigned int new_trail_length, struct GNUNET_HashCode new_trail_id) { - struct Trail *trail_list_iterator; + struct Trail *current_trail; unsigned int largest_trail_length; unsigned int largest_trail_index; struct Trail_Element *trail_element; + struct GNUNET_PeerIdentity *next_hop; unsigned int i; largest_trail_length = new_trail_length; largest_trail_index = MAXIMUM_TRAILS_PER_FINGER + 1; - GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == existing_finger->trails_count); + GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == finger->trails_count); - for (i = 0; i < existing_finger->trails_count; i++) + for (i = 0; i < finger->trails_count; i++) { - trail_list_iterator = &existing_finger->trail_list[i]; - if (trail_list_iterator->trail_length > largest_trail_length) + current_trail = &finger->trail_list[i]; + GNUNET_assert (GNUNET_YES == current_trail->is_present); + if (current_trail->trail_length > largest_trail_length) { - largest_trail_length = trail_list_iterator->trail_length; + largest_trail_length = current_trail->trail_length; largest_trail_index = i; } } @@ -2591,23 +2771,22 @@ select_and_replace_trail (struct FingerInfo *existing_finger, /* New trail is not better than existing ones. Send trail teardown. */ if (largest_trail_index == (MAXIMUM_TRAILS_PER_FINGER + 1)) { - struct GNUNET_PeerIdentity next_hop; - - memcpy (&next_hop, &new_trail[0], sizeof(struct GNUNET_PeerIdentity)); + next_hop = GDS_ROUTING_get_next_hop (new_trail_id, GDS_ROUTING_SRC_TO_DEST); GDS_ROUTING_remove_trail (new_trail_id); - GDS_NEIGHBOURS_send_trail_teardown (new_trail_id, + GDS_NEIGHBOURS_send_trail_teardown (&new_trail_id, GDS_ROUTING_SRC_TO_DEST, next_hop); return; } /* Send trail teardown message across the replaced trail. */ - struct Trail *replace_trail = &existing_finger->trail_list[largest_trail_index]; - existing_finger->trail_list[largest_trail_index].is_present = GNUNET_NO; + struct Trail *replace_trail = &finger->trail_list[largest_trail_index]; + next_hop = GDS_ROUTING_get_next_hop (replace_trail->trail_id, GDS_ROUTING_SRC_TO_DEST); GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (replace_trail->trail_id)); - GDS_NEIGHBOURS_send_trail_teardown (replace_trail->trail_id, + GDS_NEIGHBOURS_send_trail_teardown (&replace_trail->trail_id, GDS_ROUTING_SRC_TO_DEST, - replace_trail->trail_head->peer); + next_hop); + /* Free the trail. */ while (NULL != (trail_element = replace_trail->trail_head)) { @@ -2620,9 +2799,8 @@ select_and_replace_trail (struct FingerInfo *existing_finger, replace_trail->is_present = GNUNET_YES; replace_trail->trail_length = new_trail_length; replace_trail->trail_id = new_trail_id; - //FIXME: Do we need to add pointers for head and tail. - i = 0; - while (i < new_trail_length) + + for (i = 0; i < new_trail_length; i++) { struct Trail_Element *element = GNUNET_new (struct Trail_Element); element->peer = new_trail[i]; @@ -2631,6 +2809,7 @@ select_and_replace_trail (struct FingerInfo *existing_finger, replace_trail->trail_tail, element); } + /* FIXME: URGENT Are we adding the trail back to the list. */ } @@ -2648,49 +2827,120 @@ is_new_trail_unique (struct FingerInfo *existing_finger, const struct GNUNET_PeerIdentity *new_trail, unsigned int trail_length) { - struct Trail *trail_list_iterator; + struct Trail *current_trail; struct Trail_Element *trail_element; int i; int j; - int trail_unique = GNUNET_NO; GNUNET_assert (existing_finger->trails_count > 0); /* Iterate over list of trails. */ for (i = 0; i < existing_finger->trails_count; i++) { - trail_list_iterator = &existing_finger->trail_list[i]; - GNUNET_assert (GNUNET_YES == trail_list_iterator->is_present); + current_trail = &(existing_finger->trail_list[i]); + if(GNUNET_NO == current_trail->is_present) + continue; /* New trail and existing trail length are not same. */ - if (trail_list_iterator->trail_length != trail_length) + if (current_trail->trail_length != trail_length) { - trail_unique = GNUNET_YES; - continue; + return GNUNET_YES; } - trail_element = trail_list_iterator->trail_head; - for (j = 0; j < trail_list_iterator->trail_length; j++) + trail_element = current_trail->trail_head; + for (j = 0; j < current_trail->trail_length; j++) { if (0 != GNUNET_CRYPTO_cmp_peer_identity (&new_trail[j], &trail_element->peer)) { - trail_unique = GNUNET_YES; - continue; + return GNUNET_YES; } trail_element = trail_element->next; } + } + return GNUNET_NO; +} + +/** + * FIXME; In case of multiple trails, we may have a case where a trail from in + * between has been removed, then we should try to find a free slot , not simply + * add a trail at then end of the list. + * Add a new trail at a free slot in trail array of existing finger. + * @param existing_finger Finger + * @param new_finger_trail New trail from me to finger, NOT including endpoints + * @param new_finger_trail_length Total number of peers in @a new_finger_trail + * @param new_finger_trail_id Unique identifier of the trail. + */ +static void +add_new_trail (struct FingerInfo *existing_finger, + const struct GNUNET_PeerIdentity *new_trail, + unsigned int new_trail_length, + struct GNUNET_HashCode new_trail_id) +{ + struct FriendInfo *friend; + struct Trail *trail; + unsigned int i; + int free_slot = -1; + + if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail, + new_trail_length)) + return; + + for (i = 0; i < existing_finger->trails_count; i++) + { + if (GNUNET_NO == existing_finger->trail_list[i].is_present) + { + free_slot = i; + break; + } + } + + if (-1 == free_slot) + free_slot = i; + + trail = &existing_finger->trail_list[free_slot]; + GNUNET_assert (GNUNET_NO == trail->is_present); + trail->trail_id = new_trail_id; + trail->trail_length = new_trail_length; + existing_finger->trails_count++; + trail->is_present = GNUNET_YES; + if (0 == new_trail_length) + { + friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &existing_finger->finger_identity); + } + else + { + friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &new_trail[0]); + } + GNUNET_assert (NULL != friend); + friend->trails_count++; + for (i = 0; i < new_trail_length; i++) + { + struct Trail_Element *element; - trail_unique = GNUNET_NO; + element = GNUNET_new (struct Trail_Element); + element->peer = new_trail[i]; + GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head, + trail->trail_tail, + element); } - return trail_unique; + existing_finger->trail_list[free_slot].trail_head = trail->trail_head; + existing_finger->trail_list[free_slot].trail_tail = trail->trail_tail; + existing_finger->trail_list[free_slot].trail_length = new_trail_length; + existing_finger->trail_list[free_slot].trail_id = new_trail_id; + existing_finger->trail_list[free_slot].is_present = GNUNET_YES; } +#if 0 /** - * Add a new trail to existing finger. This function is called only when finger - * is not my own identity or a friend. + * FIXME; In case of multiple trails, we may have a case where a trail from in + * between has been removed, then we should try to find a free slot , not simply + * add a trail at then end of the list. + * Add a new trail at a free slot in trail array of existing finger. * @param existing_finger Finger * @param new_finger_trail New trail from me to finger, NOT including endpoints * @param new_finger_trail_length Total number of peers in @a new_finger_trail @@ -2702,22 +2952,22 @@ add_new_trail (struct FingerInfo *existing_finger, unsigned int new_trail_length, struct GNUNET_HashCode new_trail_id) { - struct Trail *trail_list_iterator; + struct Trail *trail; struct FriendInfo *first_friend; int i; + int index; if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail, new_trail_length)) - { return; - } - trail_list_iterator = &existing_finger->trail_list[existing_finger->trails_count]; - GNUNET_assert (GNUNET_NO == trail_list_iterator->is_present); - trail_list_iterator->trail_id = new_trail_id; - trail_list_iterator->trail_length = new_trail_length; + index = existing_finger->trails_count; + trail = &existing_finger->trail_list[index]; + GNUNET_assert (GNUNET_NO == trail->is_present); + trail->trail_id = new_trail_id; + trail->trail_length = new_trail_length; existing_finger->trails_count++; - trail_list_iterator->is_present = GNUNET_YES; + trail->is_present = GNUNET_YES; GNUNET_assert (NULL == (GNUNET_CONTAINER_multipeermap_get (friend_peermap, &existing_finger->finger_identity))); @@ -2734,18 +2984,20 @@ add_new_trail (struct FingerInfo *existing_finger, element = GNUNET_new (struct Trail_Element); element->peer = new_trail[i]; - GNUNET_CONTAINER_DLL_insert_tail (trail_list_iterator->trail_head, - trail_list_iterator->trail_tail, + GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head, + trail->trail_tail, element); } /* Do we need to add trail head and trail tail in the trail list itearator.*/ - + existing_finger->trail_list[index].trail_head = trail->trail_head; + existing_finger->trail_list[index].trail_tail = trail->trail_tail; + existing_finger->trail_list[index].trail_length = new_trail_length; + existing_finger->trail_list[index].trail_id = new_trail_id; + existing_finger->trail_list[index].is_present = GNUNET_YES; } - +#endif /** - * FIXME Check if this function is called for opposite direction if yes then - * take it as parameter. * Get the next hop to send trail teardown message from routing table and * then delete the entry from routing table. Send trail teardown message for a * specific trail of a finger. @@ -2762,37 +3014,45 @@ send_trail_teardown (struct FingerInfo *finger, next_hop = GDS_ROUTING_get_next_hop (trail->trail_id, GDS_ROUTING_SRC_TO_DEST); - if (NULL == next_hop) { - GNUNET_break(0); +// DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line=%d,traillength = %d", +// GNUNET_i2s(&my_identity), GNUNET_h2s(&trail->trail_id), __LINE__,trail->trail_length); return; } GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, &my_identity)); - GNUNET_assert (trail->is_present == GNUNET_YES); - - /* Finger is not a friend. */ + GNUNET_assert(GNUNET_YES == trail->is_present); if (trail->trail_length > 0) { - GNUNET_assert (NULL != (friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &trail->trail_head->peer))); + friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &trail->trail_head->peer); } else { - GNUNET_assert (NULL != (friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &finger->finger_identity))); + friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &finger->finger_identity); } - GNUNET_assert (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &friend->id)); //Fixme: assertion fails. + if(NULL == friend) + { + DEBUG ("\n LINE NO: = %d, Friend not found for trail id %s of peer %s trail length = %d", + __LINE__,GNUNET_h2s(&trail->trail_id), GNUNET_i2s(&my_identity),trail->trail_length); + return; + } + if (0 != GNUNET_CRYPTO_cmp_peer_identity (next_hop, &friend->id) + && (0 == trail->trail_length)) + { + DEBUG ("\n LINE NO: = %d, Friend not found for trail id %s of peer %s trail length = %d", + __LINE__,GNUNET_h2s(&trail->trail_id), GNUNET_i2s(&my_identity),trail->trail_length); + return; + } GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id)); friend->trails_count--; - GDS_NEIGHBOURS_send_trail_teardown (trail->trail_id, + GDS_NEIGHBOURS_send_trail_teardown (&trail->trail_id, GDS_ROUTING_SRC_TO_DEST, - friend->id); + &friend->id); } @@ -2810,10 +3070,12 @@ send_all_finger_trails_teardown (struct FingerInfo *finger) struct Trail *trail; trail = &finger->trail_list[i]; - GNUNET_assert (trail->is_present == GNUNET_YES); - send_trail_teardown (finger, trail); - trail->is_present = GNUNET_NO; - } + if (GNUNET_YES == trail->is_present) + { + send_trail_teardown (finger, trail); + trail->is_present = GNUNET_NO; + } + } } @@ -2841,26 +3103,21 @@ free_trail (struct Trail *trail) /** * Free finger and its trail. * @param finger Finger to be freed. + * @param finger_table_index Index at which finger is stored. */ static void free_finger (struct FingerInfo *finger, unsigned int finger_table_index) { struct Trail *trail; unsigned int i; - - /* Free all the trails to reach to finger */ for (i = 0; i < finger->trails_count; i++) { trail = &finger->trail_list[i]; - //FIXME: Check if there are any missing entry in this list because of - // how we insert. If not then no need of this check. if (GNUNET_NO == trail->is_present) continue; if (trail->trail_length > 0) - { free_trail (trail); - } trail->is_present = GNUNET_NO; } @@ -2870,13 +3127,9 @@ free_finger (struct FingerInfo *finger, unsigned int finger_table_index) /** - * FIXME: ensure that you are not adding any trail to reach to a friend which - * is a finger. Also decide on should you increment trails count of a friend - * which is also a finger. * Add a new entry in finger table at finger_table_index. - * In case finger identity is me or a friend, then don't add a trail. NOTE - * trail length to reach to a finger can be 0 only if the finger is a friend - * or my identity. + * In case I am my own finger, then we don't have a trail. In case of a friend, + * we have a trail with unique id and '0' trail length. * In case a finger is a friend, then increment the trails count of the friend. * @param finger_identity Peer Identity of new finger * @param finger_trail Trail to reach from me to finger (excluding both end points). @@ -2894,7 +3147,7 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, struct FingerInfo *new_entry; struct FriendInfo *first_trail_hop; struct Trail *trail; - int i = 0; + unsigned int i; new_entry = GNUNET_new (struct FingerInfo); new_entry->finger_identity = finger_identity; @@ -2902,7 +3155,8 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, new_entry->is_present = GNUNET_YES; /* If the new entry is my own identity. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity)) + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, + &finger_identity)) { new_entry->trails_count = 0; finger_table[finger_table_index] = *new_entry; @@ -2910,10 +3164,8 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, return; } - /* If finger is a friend, then we don't actually have a trail. - * Just a trail id */ - if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &finger_identity)) + /* Finger is a friend. */ + if (0 == finger_trail_length) { new_entry->trail_list[0].trail_id = trail_id; new_entry->trails_count = 1; @@ -2923,7 +3175,7 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, new_entry->trail_list[0].trail_tail = NULL; finger_table[finger_table_index] = *new_entry; GNUNET_assert (NULL != - (first_trail_hop = + (first_trail_hop = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_identity))); @@ -2932,20 +3184,15 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, return; } - /* finger trail length can be 0 only in case if finger is my identity or - finger is friend. We should never reach here. */ - GNUNET_assert (finger_trail_length > 0); - GNUNET_assert (NULL != (first_trail_hop = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[0]))); new_entry->trails_count = 1; first_trail_hop->trails_count++; - /* Copy the finger trail into trail. */ - trail = GNUNET_new (struct Trail); - while (i < finger_trail_length) + trail = &new_entry->trail_list[0]; + for(i = 0; i < finger_trail_length; i++) { struct Trail_Element *element = GNUNET_new (struct Trail_Element); @@ -2955,195 +3202,131 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head, trail->trail_tail, element); - i++; } /* Add trail to trail list. */ - new_entry->trail_list[0].trail_head = trail->trail_head; - new_entry->trail_list[0].trail_tail = trail->trail_tail; - new_entry->trail_list[0].trail_length = finger_trail_length; - new_entry->trail_list[0].trail_id = trail_id; - new_entry->trail_list[0].is_present = GNUNET_YES; + trail->trail_length = finger_trail_length; + trail->trail_id = trail_id; + trail->is_present = GNUNET_YES; finger_table[finger_table_index] = *new_entry; - //GNUNET_free (new_entry); - //GNUNET_free (trail); - return; + GNUNET_free (new_entry); } /** - * Scan the trail to check if there is any other friend in the trail other than - * first hop. If yes then shortcut the trail, send trail compression message to - * peers which are no longer part of trail and send back the updated trail - * and trail_length to calling function. - * @param finger_identity Finger whose trail we will scan. - * @param finger_trail [in, out] Trail to reach from source to finger, - * @param finger_trail_length Total number of peers in original finger_trail. - * @param finger_trail_id Unique identifier of the finger trail. - * @return updated trail length in case we shortcut the trail, else original - * trail length. + * Periodic task to verify current successor. There can be multiple trails to reach + * to successor, choose the shortest one and send verify successor message + * across that trail. + * + * @param cls closure for this task */ -static struct GNUNET_PeerIdentity * -scan_and_compress_trail (struct GNUNET_PeerIdentity finger_identity, - const struct GNUNET_PeerIdentity *trail, - unsigned int trail_length, - struct GNUNET_HashCode trail_id, - int *new_trail_length) +static void +send_verify_successor_message (void *cls) { struct FriendInfo *target_friend; - struct GNUNET_PeerIdentity *new_trail; - unsigned int i; + struct GNUNET_HashCode trail_id; + struct Trail *trail; + struct Trail_Element *element; + unsigned int trail_length; + unsigned int i = 0; + struct FingerInfo *successor; - /* I am my own finger. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity)) - { - *new_trail_length = 0; - return NULL; - } + successor = &finger_table[0]; - if (0 == trail_length) - { - *new_trail_length = 0; - return NULL; - } + /* This task will be scheduled when the result for Verify Successor is received. */ + send_verify_successor_task = NULL; - /* If finger identity is a friend. */ - if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_identity)) - { - *new_trail_length = 0; - - /* If there is trail to reach this finger/friend */ - if (trail_length > 0) + /* When verify successor is being called for first time *for current context* + * cls will be NULL. If send_verify_successor_retry_task is not NO_TASK, we + * must cancel the retry task scheduled for verify_successor of previous + * context. + */ + if (NULL == cls) + { + /* FIXME: Here we are scheduling a new verify successor task, as we + got a new successor. But a send verify successor task may be in progress. + 1. We need to be sure that this is indeed a new successor. As this function + is called even if we add a new trail to reach t old successor. + 2. Assuming the new successor is different, then verify successor message + * to old successor may be following stages. + * --> Waiting for verify successor result. Don't wait anymore. there is + * no trail to reach from old successor to me, hence, routing + * lookup will fail. + * --> Waiting for notify confirmation. again don't wait for it. notify + * confirmation will not succeded. + */ + if (send_verify_successor_retry_task != NULL) { - /* Finger is your first friend. */ - GDS_ROUTING_update_trail_next_hop (trail_id, finger_identity); - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &trail[0]))); + /* FIXME: Are we scheduling retry task as soon as we send verify message. + If yes then here before making this task, first check if the message + is for the same peer again. */ + struct VerifySuccessorContext *old_ctx = + GNUNET_SCHEDULER_cancel(send_verify_successor_retry_task); + /* old_ctx must not be NULL, as the retry task had been scheduled */ + GNUNET_assert(NULL != old_ctx); + GNUNET_free(old_ctx); + /* FIXME: Why don't we reset the task to NO_TASK here? */ + } + struct VerifySuccessorContext *ctx; + ctx = GNUNET_new(struct VerifySuccessorContext); - GDS_NEIGHBOURS_send_trail_compression (my_identity, - trail_id, finger_identity, - target_friend); - } - return NULL; + ctx->num_retries_scheduled++; + send_verify_successor_retry_task = + GNUNET_SCHEDULER_add_delayed (verify_successor_retry_time, + &send_verify_successor_message, + ctx); } - - /* For other cases, when its neither a friend nor my own identity.*/ - for (i = trail_length - 1; i > 0; i--) + else { - /* If the element at this index in trail is a friend. */ - if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail[i])) - { - struct FriendInfo *target_friend; - int j = 0; - - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &trail[0]))); - GDS_ROUTING_update_trail_next_hop (trail_id, trail[i]); - GDS_NEIGHBOURS_send_trail_compression (my_identity, - trail_id, trail[i], - target_friend); - + /* This is a retry attempt for verify_successor for a previous context */ + struct VerifySuccessorContext *ctx; - /* Copy the trail from index i to index (trail_length -1) into a new trail - * and update new trail length */ - new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length - i)); - while (i < trail_length) - { - memcpy (&new_trail[j], &trail[i], sizeof(struct GNUNET_PeerIdentity)); - j++; - i++; - } - *new_trail_length = j+1; - return new_trail; - } + ctx = cls; + ctx->num_retries_scheduled++; + send_verify_successor_retry_task = + GNUNET_SCHEDULER_add_delayed (verify_successor_retry_time, + &send_verify_successor_message, + ctx); } - /* If we did not compress the trail, return the original trail back.*/ - new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length); - *new_trail_length = trail_length; - memcpy (new_trail, trail, trail_length * sizeof (struct GNUNET_PeerIdentity)); - return new_trail; -} - - -/** - * Periodic task to verify current successor. There can be multiple trails to reach - * to successor, choose the shortest one and send verify successor message - * across that trail. - * @param cls closure for this task - * @param tc the context under which the task is running - */ -static void -send_verify_successor_message (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct FriendInfo *target_friend; - struct GNUNET_HashCode trail_id; - int i; - struct GNUNET_TIME_Relative next_send_time; - struct Trail *trail; - struct Trail_Element *element; - unsigned int trail_length; - unsigned int j = 0; - struct FingerInfo *successor; - - /* Schedule another send_find_finger_trail_message task. */ - next_send_time.rel_value_us = - DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us); - send_verify_successor_task = - GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message, - NULL); - - successor = &finger_table[0]; - i = 0; - trail = &successor->trail_list[i]; - - /* Store the successor for path tracking */ - if (track_topology && (NULL != GDS_stats)) + /* Among all the trails to reach to successor, select first one which is present.*/ + for (i = 0; i < successor->trails_count; i++) { - char *my_id_str; - char *succ_id_str; - char *key; - - my_id_str = GNUNET_strdup (GNUNET_i2s (&my_identity)); - succ_id_str = GNUNET_strdup (GNUNET_i2s - (&successor->finger_identity)); - GNUNET_asprintf (&key, "XDHT:0:%.4s:%.4s", my_id_str, succ_id_str); - GNUNET_free (my_id_str); - GNUNET_free (succ_id_str); - GNUNET_STATISTICS_update (GDS_stats, "key", 1, 0); - GNUNET_free (key); + trail = &successor->trail_list[i]; + if(GNUNET_YES == trail->is_present) + break; } + /* No valid trail found to reach to successor. */ + if (i == successor->trails_count) + return; + GNUNET_assert(0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &successor->finger_identity)); - /* Trail stored at this index. */ GNUNET_assert (GNUNET_YES == trail->is_present); - trail_id = trail->trail_id; + if (NULL == GDS_ROUTING_get_next_hop(trail_id,GDS_ROUTING_SRC_TO_DEST)) + { + DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line %u", + GNUNET_i2s (&my_identity), + GNUNET_h2s (&trail->trail_id), + __LINE__); + GNUNET_break(0); + return; + } trail_length = trail->trail_length; - if (trail_length > 0) { /* Copy the trail into peer list. */ struct GNUNET_PeerIdentity peer_list[trail_length]; - element = trail->trail_head; - while (j < trail_length) + for(i = 0; i < trail_length; i++) { - peer_list[j] = element->peer; + peer_list[i] = element->peer; element = element->next; - j++; } - GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &peer_list[0]))); @@ -3151,7 +3334,6 @@ send_verify_successor_message (void *cls, successor->finger_identity, trail_id, peer_list, trail_length, target_friend); - return; } else { @@ -3162,19 +3344,18 @@ send_verify_successor_message (void *cls, successor->finger_identity, trail_id, NULL, 0, target_friend); - return; } } /** + * FIXME: should this be a periodic task, incrementing the search finger index? * Update the current search finger index. - * - * FIXME document parameters! + * @a finger_identity + * @a finger_table_index */ static void -update_current_search_finger_index (struct GNUNET_PeerIdentity finger_identity, - unsigned int finger_table_index) +update_current_search_finger_index (unsigned int finger_table_index) { struct FingerInfo *successor; @@ -3188,15 +3369,15 @@ update_current_search_finger_index (struct GNUNET_PeerIdentity finger_identity, /* We were looking for immediate successor. */ if (0 == current_search_finger_index) { - /* Start looking for immediate predecessor. */ current_search_finger_index = PREDECESSOR_FINGER_ID; - - if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity)) + if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &successor->finger_identity)) { - if (GNUNET_SCHEDULER_NO_TASK == send_verify_successor_task) - send_verify_successor_task = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL); + if (NULL == send_verify_successor_task) + { + send_verify_successor_task = + GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL); + } } - return; } @@ -3279,22 +3460,21 @@ get_finger_table_index (uint64_t ultimate_destination_finger_value, /** * Remove finger and its associated data structures from finger table. - * @param finger Finger to be removed. + * @param existing_finger Finger to be removed which is in finger table. + * @param finger_table_index Index in finger table where @a existing_finger + * is stored. */ static void remove_existing_finger (struct FingerInfo *existing_finger, unsigned int finger_table_index) { - struct FingerInfo *finger; - - finger = &finger_table[finger_table_index]; - GNUNET_assert (GNUNET_YES == finger->is_present); + GNUNET_assert (GNUNET_YES == existing_finger->is_present); /* If I am my own finger, then we have no trails. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&existing_finger->finger_identity, &my_identity)) { - finger->is_present = GNUNET_NO; + existing_finger->is_present = GNUNET_NO; memset ((void *)&finger_table[finger_table_index], 0, sizeof (finger_table[finger_table_index])); return; @@ -3302,9 +3482,8 @@ remove_existing_finger (struct FingerInfo *existing_finger, /* For all other fingers, send trail teardown across all the trails to reach finger, and free the finger. */ - send_all_finger_trails_teardown (finger); - free_finger (finger, finger_table_index); - return; + send_all_finger_trails_teardown (existing_finger); + free_finger (existing_finger, finger_table_index); } @@ -3338,9 +3517,8 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, struct GNUNET_HashCode finger_trail_id) { struct FingerInfo *existing_finger; - const struct GNUNET_PeerIdentity *closest_peer; + struct GNUNET_PeerIdentity closest_peer; struct FingerInfo *successor; - int updated_finger_trail_length; unsigned int finger_table_index; /* Get the finger_table_index corresponding to finger_value we got from network.*/ @@ -3353,26 +3531,35 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, return; } - /* New entry same as successor. */ + /* Check if new entry is same as successor. */ if ((0 != finger_table_index) && (PREDECESSOR_FINGER_ID != finger_table_index)) { successor = &finger_table[0]; if (GNUNET_NO == successor->is_present) { - GNUNET_break_op (0); + GNUNET_break (0); //ASSERTION FAILS HERE. FIXME return; } if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &successor->finger_identity)) { + if (0 == fingers_round_count) + { + find_finger_trail_task_next_send_time = + GNUNET_TIME_STD_BACKOFF(find_finger_trail_task_next_send_time); + } + else + fingers_round_count--; current_search_finger_index = 0; - /* We slow down the find_finger_trail_task as we have completed the circle. */ - next_send_time = GNUNET_TIME_STD_BACKOFF(next_send_time); - + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# FINGERS_COUNT"), (int64_t) total_fingers_found, + GNUNET_NO); + total_fingers_found = 0; return; } - + struct FingerInfo prev_finger; prev_finger = finger_table[finger_table_index - 1]; if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, @@ -3383,29 +3570,20 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, } } + total_fingers_found++; existing_finger = &finger_table[finger_table_index]; /* No entry present in finger_table for given finger map index. */ if (GNUNET_NO == existing_finger->is_present) { - struct GNUNET_PeerIdentity *updated_trail; - - /* Shorten the trail if possible. */ - updated_finger_trail_length = finger_trail_length; - updated_trail = scan_and_compress_trail (finger_identity, finger_trail, - finger_trail_length, - finger_trail_id, - &updated_finger_trail_length); - - add_new_finger (finger_identity, updated_trail, - updated_finger_trail_length, + /* Shorten the trail if possible. */ + add_new_finger (finger_identity, finger_trail, + finger_trail_length, finger_trail_id, finger_table_index); - update_current_search_finger_index (finger_identity, - finger_table_index); + update_current_search_finger_index (finger_table_index); return; } - /* If existing entry and finger identity are not same. */ if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity), &finger_identity)) @@ -3416,19 +3594,11 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, is_predecessor); /* If the new finger is the closest peer. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, closest_peer)) + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &closest_peer)) { - struct GNUNET_PeerIdentity *updated_trail; - /* Shorten the trail if possible. */ - updated_finger_trail_length = finger_trail_length; - updated_trail = - scan_and_compress_trail (finger_identity, finger_trail, - finger_trail_length, finger_trail_id, - &updated_finger_trail_length); remove_existing_finger (existing_finger, finger_table_index); - add_new_finger (finger_identity, updated_trail, updated_finger_trail_length, + add_new_finger (finger_identity, finger_trail, finger_trail_length, finger_trail_id, finger_table_index); - } else { @@ -3437,13 +3607,13 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, if (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &my_identity)) { if (finger_trail_length > 0) - GDS_NEIGHBOURS_send_trail_teardown (finger_trail_id, + GDS_NEIGHBOURS_send_trail_teardown (&finger_trail_id, GDS_ROUTING_SRC_TO_DEST, - finger_trail[0]); + &finger_trail[0]); else - GDS_NEIGHBOURS_send_trail_teardown (finger_trail_id, + GDS_NEIGHBOURS_send_trail_teardown (&finger_trail_id, GDS_ROUTING_SRC_TO_DEST, - finger_identity); + &finger_identity); } } } @@ -3455,33 +3625,20 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, { return; } - /* If the existing finger is not a friend. */ - if (NULL == - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &existing_finger->finger_identity)) - { - struct GNUNET_PeerIdentity *updated_trail; - - /* Shorten the trail if possible. */ - updated_finger_trail_length = finger_trail_length; - updated_trail = - scan_and_compress_trail (finger_identity, finger_trail, - finger_trail_length, finger_trail_id, - &updated_finger_trail_length); - /* If there is space to store more trails. */ - if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER) - add_new_trail (existing_finger, updated_trail, - updated_finger_trail_length, finger_trail_id); - else - select_and_replace_trail (existing_finger, updated_trail, - updated_finger_trail_length, finger_trail_id); - } + /* If there is space to store more trails. */ + if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER) + add_new_trail (existing_finger, finger_trail, + finger_trail_length, finger_trail_id); + else + select_and_replace_trail (existing_finger, finger_trail, + finger_trail_length, finger_trail_id); } - update_current_search_finger_index (finger_identity, finger_table_index); + update_current_search_finger_index (finger_table_index); return; } + /** * Core handler for P2P put messages. * @param cls closure @@ -3496,14 +3653,18 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, { struct PeerPutMessage *put; struct GNUNET_PeerIdentity *put_path; + struct GNUNET_PeerIdentity current_best_known_dest; struct GNUNET_PeerIdentity best_known_dest; + struct GNUNET_HashCode received_intermediate_trail_id; struct GNUNET_HashCode intermediate_trail_id; - struct GNUNET_PeerIdentity *next_hop; + struct GNUNET_PeerIdentity next_hop; + struct GNUNET_PeerIdentity *next_routing_hop; enum GNUNET_DHT_RouteOption options; struct GNUNET_HashCode test_key; void *payload; size_t msize; uint32_t putlen; + uint32_t hop_count; size_t payload_size; uint64_t key_value; @@ -3516,27 +3677,36 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, put = (struct PeerPutMessage *) message; putlen = ntohl (put->put_path_length); - - if ((msize < sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)) || (putlen > - GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) + GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_OK; } +#if ENABLE_MALICIOUS + if(1 == act_malicious) + { + DEBUG("\n I AM MALICIOUS PUT_REQUEST_DROPPED for key = %ss",GNUNET_h2s(&put->key)); + return GNUNET_OK; + } +#endif + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), (int64_t) msize, + GNUNET_NO); - best_known_dest = put->best_known_destination; + current_best_known_dest = put->best_known_destination; put_path = (struct GNUNET_PeerIdentity *) &put[1]; payload = &put_path[putlen]; options = ntohl (put->options); - intermediate_trail_id = put->intermediate_trail_id; - + received_intermediate_trail_id = put->intermediate_trail_id; + hop_count = ntohl(put->hop_count); payload_size = msize - (sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)); - + hop_count++; switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type), payload, payload_size, &test_key)) { @@ -3564,6 +3734,7 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, { switch (GNUNET_BLOCK_evaluate (GDS_block_context, ntohl (put->block_type), + GNUNET_BLOCK_EO_NONE, NULL, /* query */ NULL, 0, /* bloom filer */ NULL, 0, /* xquery */ @@ -3585,46 +3756,53 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, } } - /* extend 'put path' by sender */ + /* Check if you are already a part of put path. */ + unsigned int i; + for (i = 0; i < putlen; i++) + { + if(0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &put_path[i])) + { + putlen = i; + break; + } + } + + /* Add yourself to the list. */ struct GNUNET_PeerIdentity pp[putlen + 1]; - if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) + //if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) + if (1) { memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity)); - pp[putlen] = *peer; + pp[putlen] = my_identity; putlen++; } else putlen = 0; memcpy (&key_value, &(put->key), sizeof (uint64_t)); - if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity))) + struct Closest_Peer successor; + key_value = GNUNET_ntohll (key_value); + successor = find_local_best_known_next_hop (key_value, + GDS_FINGER_TYPE_NON_PREDECESSOR); + next_hop = successor.next_hop; + intermediate_trail_id = successor.trail_id; + best_known_dest = successor.best_known_destination; + + if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_best_known_dest, &my_identity))) { - next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id, - GDS_ROUTING_SRC_TO_DEST); - if (NULL == next_hop) + next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id, + GDS_ROUTING_SRC_TO_DEST); + if (NULL != next_routing_hop) { - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop ("# Next hop to forward the packet not found " - "trail setup request, packet dropped."), - 1, GNUNET_NO); - return GNUNET_SYSERR; + next_hop = *next_routing_hop; + intermediate_trail_id = received_intermediate_trail_id; + best_known_dest = current_best_known_dest; } } - else - { - struct Closest_Peer successor; - key_value = GNUNET_ntohll (key_value); - successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR); - - next_hop = GNUNET_new (struct GNUNET_PeerIdentity); - *next_hop = successor.next_hop; - intermediate_trail_id = successor.trail_id; - best_known_dest = successor.best_known_destination; - } GDS_CLIENTS_process_put (options, ntohl (put->block_type), - ntohl (put->hop_count), + hop_count, ntohl (put->desired_replication_level), putlen, pp, GNUNET_TIME_absolute_ntoh (put->expiration_time), @@ -3635,25 +3813,65 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, /* I am the final destination */ if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &best_known_dest)) { + DEBUG("\n PUT_REQUEST_SUCCESSFUL for key = %s",GNUNET_h2s(&put->key)); GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time), &(put->key),putlen, pp, ntohl (put->block_type), payload_size, payload); } else { - GDS_NEIGHBOURS_send_put (&put->key, - ntohl (put->block_type),ntohl (put->options), - ntohl (put->desired_replication_level), - best_known_dest, intermediate_trail_id, next_hop, - ntohl (put->hop_count), putlen, pp, - GNUNET_TIME_absolute_ntoh (put->expiration_time), - payload, payload_size); +#if ENABLE_MALICIOUS + if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination, + &successor.next_hop)) + { + struct FingerInfo *next_hop_finger; + unsigned int i; + + next_hop_finger = &finger_table[successor.finger_table_index]; + for (i = 0; i < next_hop_finger->trails_count; i++) + { + if (GNUNET_YES == next_hop_finger->trail_list[i].is_present) + { + if(0 == next_hop_finger->trail_list[i].trail_length) + { + GDS_NEIGHBOURS_send_put (&put->key, + ntohl (put->block_type),ntohl (put->options), + ntohl (put->desired_replication_level), + best_known_dest, intermediate_trail_id, &next_hop, + hop_count, putlen, pp, + GNUNET_TIME_absolute_ntoh (put->expiration_time), + payload, payload_size); + return GNUNET_OK; + } + next_hop = next_hop_finger->trail_list[i].trail_head->peer; + GDS_NEIGHBOURS_send_put (&put->key, + ntohl (put->block_type),ntohl (put->options), + ntohl (put->desired_replication_level), + best_known_dest, + next_hop_finger->trail_list[i].trail_id, + &next_hop, hop_count, putlen, pp, + GNUNET_TIME_absolute_ntoh (put->expiration_time), + payload, payload_size); + } + } + return GNUNET_OK; } +#endif + GDS_NEIGHBOURS_send_put (&put->key, + ntohl (put->block_type),ntohl (put->options), + ntohl (put->desired_replication_level), + best_known_dest, intermediate_trail_id, &next_hop, + hop_count, putlen, pp, + GNUNET_TIME_absolute_ntoh (put->expiration_time), + payload, payload_size); + } return GNUNET_OK; } /** + * FIXME: Check for loop in the request. If you already are part of get path, + * then you need to reset the get path length. * Core handler for p2p get requests. * * @param cls closure @@ -3669,10 +3887,15 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, const struct PeerGetMessage *get; const struct GNUNET_PeerIdentity *get_path; struct GNUNET_PeerIdentity best_known_dest; + struct GNUNET_PeerIdentity current_best_known_dest; struct GNUNET_HashCode intermediate_trail_id; - struct GNUNET_PeerIdentity *next_hop; + struct GNUNET_HashCode received_intermediate_trail_id; + struct Closest_Peer successor; + struct GNUNET_PeerIdentity next_hop; + struct GNUNET_PeerIdentity *next_routing_hop; uint32_t get_length; uint64_t key_value; + uint32_t hop_count; size_t msize; msize = ntohs (message->size); @@ -3684,76 +3907,130 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, get = (const struct PeerGetMessage *)message; get_length = ntohl (get->get_path_length); - best_known_dest = get->best_known_destination; - intermediate_trail_id = get->intermediate_trail_id; - get_path = (const struct GNUNET_PeerIdentity *)&get[1]; - if ((msize < sizeof (struct PeerGetMessage) + get_length * sizeof (struct GNUNET_PeerIdentity)) || (get_length > - GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) + GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } - /* Add sender to get path */ - struct GNUNET_PeerIdentity gp[get_length + 1]; - if (get_length > 0) - memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity)); - gp[get_length] = *peer; - get_length = get_length + 1; +#if ENABLE_MALICIOUS + if(1 == act_malicious) + { + DEBUG("I am malicious,GET_REQUEST_DROPPED for key = %s. \n",GNUNET_h2s(&get->key)); + return GNUNET_OK; + } +#endif + current_best_known_dest = get->best_known_destination; + received_intermediate_trail_id = get->intermediate_trail_id; + get_path = (const struct GNUNET_PeerIdentity *)&get[1]; + hop_count = get->hop_count; + hop_count++; + + + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); memcpy (&key_value, &(get->key), sizeof (uint64_t)); key_value = GNUNET_ntohll (key_value); - /* I am not the final destination. I am part of trail to reach final dest. */ - if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity))) + /* Check if you are already a part of get path. */ + unsigned int i; + for (i = 0; i < get_length; i++) { - next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id, - GDS_ROUTING_SRC_TO_DEST); - if (NULL == next_hop) + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &get_path[i])) { - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop ("# Next hop to forward the packet not found " - "GET request, packet dropped."), - 1, GNUNET_NO); - return GNUNET_SYSERR; + get_length = i; + break; } } - else - { - struct Closest_Peer successor; - - successor = find_successor (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR); - next_hop = GNUNET_new (struct GNUNET_PeerIdentity); - *next_hop = successor.next_hop; - best_known_dest = successor.best_known_destination; - intermediate_trail_id = successor.trail_id; - } - GDS_CLIENTS_process_get (get->options, get->block_type,get->hop_count, + /* Add yourself in the get path. */ + struct GNUNET_PeerIdentity gp[get_length + 1]; + memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity)); + gp[get_length] = my_identity; + get_length = get_length + 1; + GDS_CLIENTS_process_get (get->options, get->block_type, hop_count, get->desired_replication_level, get->get_path_length, gp, &get->key); + + + successor = find_local_best_known_next_hop (key_value, + GDS_FINGER_TYPE_NON_PREDECESSOR); + next_hop = successor.next_hop; + best_known_dest = successor.best_known_destination; + intermediate_trail_id = successor.trail_id; + /* I am not the final destination. I am part of trail to reach final dest. */ + if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_best_known_dest, &my_identity))) + { + next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id, + GDS_ROUTING_SRC_TO_DEST); + if (NULL != next_routing_hop) + { + next_hop = *next_routing_hop; + best_known_dest = current_best_known_dest; + intermediate_trail_id = received_intermediate_trail_id; + } + } + /* I am the final destination. */ if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &best_known_dest)) { - struct GNUNET_PeerIdentity final_get_path[get_length+1]; - - memcpy (final_get_path, gp, get_length * sizeof (struct GNUNET_PeerIdentity)); - memcpy (&final_get_path[get_length], &my_identity, sizeof (struct GNUNET_PeerIdentity)); - get_length = get_length + 1; - - GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0, - get_length, final_get_path, - &final_get_path[get_length-2], &my_identity); + if (1 == get_length) + { + DEBUG("\n GET_REQUEST DONE for key = %s",GNUNET_h2s(&get->key)); + GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, + NULL, 0, 1, &my_identity, NULL,&my_identity); + } + else + { + GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0, + get_length, gp, &gp[get_length - 2], + &my_identity); + } } else { + +#if ENABLE_MALICIOUS + if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination, + &successor.next_hop)) + { + struct FingerInfo *next_hop_finger; + unsigned int i; + + next_hop_finger = &finger_table[successor.finger_table_index]; + for (i = 0; i < next_hop_finger->trails_count; i++) + { + if(0 == next_hop_finger->trail_list[i].trail_length) + { + GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options, + get->desired_replication_level, best_known_dest, + intermediate_trail_id, &next_hop, hop_count, + get_length, gp); + return GNUNET_OK; + } + if (GNUNET_YES == next_hop_finger->trail_list[i].is_present) + { + next_hop = next_hop_finger->trail_list[i].trail_head->peer; + GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options, + get->desired_replication_level, best_known_dest, + next_hop_finger->trail_list[i].trail_id, + &next_hop, hop_count, + get_length, gp); + } + } + return GNUNET_OK; + } +#endif GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options, get->desired_replication_level, best_known_dest, - intermediate_trail_id, next_hop, 0, + intermediate_trail_id, &next_hop, hop_count, get_length, gp); } return GNUNET_YES; @@ -3798,13 +4075,18 @@ handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, getlen * sizeof (struct GNUNET_PeerIdentity) + putlen * sizeof (struct GNUNET_PeerIdentity)) || (getlen > - GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) || + GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) || (putlen > - GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))) + GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))) { GNUNET_break_op (0); return GNUNET_YES; } + DEBUG("GET_RESULT FOR DATA_SIZE = %lu\n",msize); + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); put_path = (const struct GNUNET_PeerIdentity *) &get_result[1]; get_path = &put_path[putlen]; @@ -3814,7 +4096,8 @@ handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0])))) { - GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key), + GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (get_result->expiration_time), + &(get_result->key), getlen, get_path, putlen, put_path, get_result->type, payload_size, payload); return GNUNET_YES; @@ -3824,13 +4107,21 @@ handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, current_path_index = search_my_index (get_path, getlen); if (-1 == current_path_index ) { + DEBUG ("No entry found in get path.\n"); + GNUNET_break (0); + return GNUNET_SYSERR; + } + if((getlen + 1) == current_path_index) + { + DEBUG("Present twice in get path. Not allowed. \n"); GNUNET_break (0); return GNUNET_SYSERR; } GDS_NEIGHBOURS_send_get_result (&(get_result->key), get_result->type, &get_path[current_path_index - 1], &(get_result->querying_peer), putlen, put_path, - getlen, get_path, get_result->expiration_time, + getlen, get_path, + GNUNET_TIME_absolute_ntoh (get_result->expiration_time), payload, payload_size); return GNUNET_YES; } @@ -3848,6 +4139,7 @@ handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, * finger, then it is the trail id to reach to * that finger, else set to 0. * @param is_predecessor Are we looking for closest successor or predecessor. + * @param source Source of trail setup message. * @param current_dest In case you are part of trail, then finger to which * we should forward the message. Else my own identity * @return Closest Peer for @a final_dest_finger_val @@ -3856,39 +4148,40 @@ static struct Closest_Peer get_local_best_known_next_hop (uint64_t final_dest_finger_val, struct GNUNET_HashCode intermediate_trail_id, unsigned int is_predecessor, - struct GNUNET_PeerIdentity prev_hop, struct GNUNET_PeerIdentity source, struct GNUNET_PeerIdentity *current_dest) { struct Closest_Peer peer; - /* Find a local best known peer. */ - peer = find_successor (final_dest_finger_val, is_predecessor);//FIXME: chnage to better name + peer = find_local_best_known_next_hop (final_dest_finger_val, is_predecessor); /* Am I just a part of a trail towards a finger (current_destination)? */ - /* Select best successor among one found locally and current_destination - * that we got from network.*/ if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_dest) && 0 != GNUNET_CRYPTO_cmp_peer_identity (&peer.best_known_destination, current_dest)) { - const struct GNUNET_PeerIdentity *closest_peer; + struct GNUNET_PeerIdentity closest_peer; + /* Select best successor among one found locally and current_destination + * that we got from network.*/ closest_peer = select_closest_peer (&peer.best_known_destination, current_dest, final_dest_finger_val, is_predecessor); /* Is current dest (end point of the trail of which I am a part) closest_peer? */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (current_dest, closest_peer)) + if (0 == GNUNET_CRYPTO_cmp_peer_identity (current_dest, &closest_peer)) { struct GNUNET_PeerIdentity *next_hop; - + next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id, GDS_ROUTING_SRC_TO_DEST); - /* It may happen that trail teardown message got delayed and hence, - the previous hop sent the message over intermediate trail id.In that - case next_hop could be NULL. */ + /* next_hop NULL is a valid case. This intermediate trail id is set by + some other finger, and while this trail setup is in progress, that other + peer might have found a better trail ,and send trail teardown message + across the network. In case we got the trail teardown message first, + then next_hop will be NULL. A possible solution could be to keep track + * of all removed trail id, and be sure that there is no other reason . */ if(NULL != next_hop) { peer.next_hop = *next_hop; @@ -3900,41 +4193,6 @@ get_local_best_known_next_hop (uint64_t final_dest_finger_val, return peer; } -#if 0 -/** - * Check if peer is already present in the trail. - * @param peer - * @param trail - * @param trail_length - * @return - */ -static struct GNUNET_PeerIdentity * -check_for_duplicate_entries (const struct GNUNET_PeerIdentity *trail, - unsigned int trail_length, - unsigned int *updated_trail_length) -{ - struct GNUNET_PeerIdentity *updated_trail; - unsigned int i; - unsigned int j; - - /* It may happen that there are more than one peer present twice. - but we don't want to*/ - for(i = 0;i < trail_length; i++) - { - for(j = i+1; j < trail_length; j++) - { - if(0 != GNUNET_CRYPTO_cmp_peer_identity (&trail[i],&trail[j])) - continue; - - /* If you found a duplicate entry in the trail, then you should - * have the entry at i should point to next of entry stored at j*/ - - /* In case j = (trail_length - 1), then it should NULL. */ - - } - } -} -#endif /* * Core handle for PeerTrailSetupMessage. @@ -3952,12 +4210,12 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_PeerIdentity current_dest; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity source; - uint64_t final_dest_finger_val; struct GNUNET_HashCode intermediate_trail_id; struct GNUNET_HashCode trail_id; unsigned int is_predecessor; uint32_t trail_length; - unsigned int i; + uint64_t final_dest_finger_val; + int i; size_t msize; msize = ntohs (message->size); @@ -3968,14 +4226,19 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, } trail_setup = (const struct PeerTrailSetupMessage *) message; - trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/ - sizeof (struct GNUNET_PeerIdentity); if ((msize - sizeof (struct PeerTrailSetupMessage)) % sizeof (struct GNUNET_PeerIdentity) != 0) { GNUNET_break_op (0); return GNUNET_OK; } + trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/ + sizeof (struct GNUNET_PeerIdentity); + + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_setup[1]; current_dest = trail_setup->best_known_destination; @@ -3988,50 +4251,46 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, /* Did the friend insert its ID in the trail list? */ if (trail_length > 0 && - 0 != memcmp (&trail_peer_list[trail_length-1], peer, sizeof (*peer))) + 0 != memcmp (&trail_peer_list[trail_length-1], peer, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_SYSERR; } - + /* If I was the source and got the message back, then set trail length to 0.*/ if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &source)) { - /* IF (!) the peers know the destinations of the trails in their routing - * table, then: - * - * This shoud only happen after 1 hop, since the first message is sent - * to random friend, and we can happen to be on the best trail to the dest. - * If the first friend selects someone else, the request should never come - * back to us. - * - * (TODO) - */ - // GNUNET_break_op (1 == trail_length); trail_length = 0; } /* Check if you are present in the trail seen so far? */ - if(trail_length > 0) + for (i = 0; i < trail_length ; i++) { - for (i = 0; i < trail_length ; i++) + if(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail_peer_list[i],&my_identity)) { - if(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail_peer_list[i],&my_identity)) - { - //Here if you already were present in the trail. then you - // shoudl trail length to i + 1 - trail_length = i+1; - break; - } + /* We will add ourself later in code, if NOT destination. */ + trail_length = i; + break; } } - + /* Is my routing table full? */ if (GNUNET_YES == GDS_ROUTING_threshold_reached()) { - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))); + if (trail_length > 0) + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &trail_peer_list[trail_length - 1]); + else + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &source); + if(NULL == target_friend) + { + DEBUG ("\n friend not found"); + GNUNET_break(0); + return GNUNET_OK; + } GDS_NEIGHBOURS_send_trail_rejection (source, final_dest_finger_val, my_identity, is_predecessor, trail_peer_list, trail_length, @@ -4045,7 +4304,6 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, get_local_best_known_next_hop (final_dest_finger_val, intermediate_trail_id, is_predecessor, - *peer, source, ¤t_dest); @@ -4053,12 +4311,6 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&next_peer.best_known_destination, &my_identity))) { - /* If I was not the source of this message for which now I am destination */ - if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity)) - { - GDS_ROUTING_add (trail_id, *peer, my_identity); - } - if(0 == GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity)) { finger_table_add (my_identity, NULL, 0, is_predecessor, @@ -4067,15 +4319,18 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, } if (trail_length > 0) - target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer); + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &trail_peer_list[trail_length-1]); else - target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &source); + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &source); if (NULL == target_friend) { GNUNET_break_op (0); return GNUNET_SYSERR; } - + GDS_ROUTING_add (trail_id, target_friend->id, my_identity); GDS_NEIGHBOURS_send_trail_setup_result (source, my_identity, target_friend, trail_length, @@ -4085,11 +4340,14 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, } else /* I'm not the final destination. */ { - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &next_peer.next_hop))); - + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &next_peer.next_hop); + if(NULL == target_friend) + { + DEBUG ("\n target friend not found for peer = %s", GNUNET_i2s(&next_peer.next_hop)); + GNUNET_break (0); + return GNUNET_OK; + } if (0 != GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &source)) { /* Add yourself to list of peers. */ @@ -4098,7 +4356,6 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); peer_list[trail_length] = my_identity; - GDS_NEIGHBOURS_send_trail_setup (source, final_dest_finger_val, next_peer.best_known_destination, @@ -4117,92 +4374,17 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } -#if 0 -/* FIXME: here we are calculating my_index and comparing also in this function. - And we are doing it again here in this function. Re factor the code. */ + /** - * FIXME: Should we call this function everywhere in all the handle functions - * where we have a trail to verify from or a trail id. something like - * if prev hop is not same then drop the message. - * Check if sender_peer and peer from which we should receive the message are - * same or different. - * @param trail_peer_list List of peers in trail - * @param trail_length Total number of peers in @a trail_peer_list - * @param sender_peer Peer from which we got the message. - * @param finger_identity Finger to which trail is setup. It is not part of trail. - * @return #GNUNET_YES if sender_peer and peer from which we should receive the - * message are different. - * #GNUNET_NO if sender_peer and peer from which we should receive the - * message are different. + * Core handle for p2p trail setup result messages. + * @param closure + * @param message message + * @param peer sender of this message. + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int -is_sender_peer_correct (const struct GNUNET_PeerIdentity *trail_peer_list, - unsigned int trail_length, - const struct GNUNET_PeerIdentity *sender_peer, - struct GNUNET_PeerIdentity finger_identity, - struct GNUNET_PeerIdentity source_peer) -{ - int my_index; - - /* I am the source peer. */ - if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&source_peer, - &my_identity))) - { - /* Is the first element of the trail is sender_peer.*/ - if (trail_length > 0) - { - if (0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[0], - sender_peer)) - return GNUNET_NO; - } - else - { - /* Is finger the sender peer? */ - if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer, - &finger_identity)) - return GNUNET_NO; - } - } - else - { - /* Get my current location in the trail. */ - my_index = search_my_index (trail_peer_list, trail_length); - if (-1 == my_index) - return GNUNET_NO; - - /* I am the last element in the trail. */ - if ((trail_length - 1) == my_index) - { - /* Is finger the sender_peer? */ - if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer, - &finger_identity)) - return GNUNET_NO; - } - else - { - /* Is peer after me in trail the sender peer? */ - if (0 != GNUNET_CRYPTO_cmp_peer_identity (sender_peer, - &trail_peer_list[my_index + 1])) - return GNUNET_NO; - } - } - return GNUNET_YES; -} -#endif - - -/** - * FIXME: we should also add a case where we search if we are present in the trail - * twice. - * Core handle for p2p trail setup result messages. - * @param closure - * @param message message - * @param peer sender of this message. - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) +handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) { const struct PeerTrailSetupResultMessage *trail_result; const struct GNUNET_PeerIdentity *trail_peer_list; @@ -4225,14 +4407,19 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p } trail_result = (const struct PeerTrailSetupResultMessage *) message; - trail_length = (msize - sizeof (struct PeerTrailSetupResultMessage))/ - sizeof (struct GNUNET_PeerIdentity); if ((msize - sizeof (struct PeerTrailSetupResultMessage)) % sizeof (struct GNUNET_PeerIdentity) != 0) { GNUNET_break_op (0); return GNUNET_OK; } + trail_length = (msize - sizeof (struct PeerTrailSetupResultMessage))/ + sizeof (struct GNUNET_PeerIdentity); + + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); is_predecessor = ntohl (trail_result->is_predecessor); querying_peer = trail_result->querying_peer; @@ -4242,30 +4429,19 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p ulitmate_destination_finger_value = GNUNET_ntohll (trail_result->ulitmate_destination_finger_value); - /* FIXME: here we are calculating my_index and comparing also in this function. - And we are doing it again here in this function. Re factor the code. */ - /* Ensure that sender peer is the peer from which we were expecting the message. */ -#if 0 - if (GNUNET_NO == is_sender_peer_correct (trail_peer_list, - trail_length, - peer, finger_identity, querying_peer)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } -#endif - - /*TODO:URGENT Check if I am already present in the trail. If yes then its an error, - as in trail setup we ensure that it should never happen. */ - /* Am I the one who initiated the query? */ if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity))) { - /* If I am my own finger identity, error. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &finger_identity)) + /* Check that you got the message from the correct peer. */ + if (trail_length > 0) { - GNUNET_break_op (0); - return GNUNET_SYSERR; + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[0], + peer)); + } + else + { + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, + peer)); } GDS_ROUTING_add (trail_id, my_identity, *peer); finger_table_add (finger_identity, trail_peer_list, trail_length, @@ -4277,14 +4453,43 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p my_index = search_my_index (trail_peer_list, trail_length); if (-1 == my_index) { + DEBUG ("Not found in trail\n"); + GNUNET_break_op(0); + return GNUNET_SYSERR; + } + //TODO; return -2. + if ((trail_length + 1) == my_index) + { + DEBUG ("Found twice in trail.\n"); GNUNET_break_op(0); return GNUNET_SYSERR; } + //TODO; Refactor code here and above to check if sender peer is correct if (my_index == 0) + { + if(trail_length > 1) + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[1], + peer)); + else + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, + peer)); next_hop = trail_result->querying_peer; + } else + { + if(my_index == trail_length - 1) + { + GNUNET_assert(0 == + GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, + peer)); + } + else + GNUNET_assert(0 == + GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[my_index + 1], + peer)); next_hop = trail_peer_list[my_index - 1]; + } target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop); if (NULL == target_friend) @@ -4292,16 +4497,7 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p GNUNET_break_op (0); return GNUNET_SYSERR; } - - if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->querying_peer), - &(trail_result->finger_identity)))) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GDS_ROUTING_add (trail_id, next_hop, *peer); - GDS_NEIGHBOURS_send_trail_setup_result (querying_peer, finger_identity, target_friend, trail_length, trail_peer_list, is_predecessor, @@ -4361,8 +4557,6 @@ get_shortest_trail (struct FingerInfo *finger, struct GNUNET_PeerIdentity *trail_list; unsigned int i; - trail = GNUNET_new (struct Trail); - /* Get the shortest trail to reach to current successor. */ for (i = 0; i < finger->trails_count; i++) { @@ -4387,6 +4581,7 @@ get_shortest_trail (struct FingerInfo *finger, /* Copy the shortest trail and return. */ trail = &finger->trail_list[shortest_trail_index]; trail_element = trail->trail_head; + trail_list = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)* shortest_trail_length); @@ -4402,6 +4597,85 @@ get_shortest_trail (struct FingerInfo *finger, } +/** + * Check if trail_1 and trail_2 have any common element. If yes then join + * them at common element. trail_1 always preceeds trail_2 in joined trail. + * @param trail_1 Trail from source to me, NOT including endpoints. + * @param trail_1_len Total number of peers @a trail_1 + * @param trail_2 Trail from me to current predecessor, NOT including endpoints. + * @param trail_2_len Total number of peers @a trail_2 + * @param joined_trail_len Total number of peers in combined trail of trail_1 + * trail_2. + * @return Joined trail. + */ +static struct GNUNET_PeerIdentity * +check_for_duplicate_entries (const struct GNUNET_PeerIdentity *trail_1, + unsigned int trail_1_len, + struct GNUNET_PeerIdentity *trail_2, + unsigned int trail_2_len, + unsigned int *joined_trail_len) +{ + struct GNUNET_PeerIdentity *joined_trail; + unsigned int i; + unsigned int j; + unsigned int k; + + for (i = 0; i < trail_1_len; i++) + { + for (j = 0; j < trail_2_len; j++) + { + if(0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_1[i],&trail_2[j])) + continue; + + *joined_trail_len = i + (trail_2_len - j); + joined_trail = GNUNET_malloc (*joined_trail_len * + sizeof(struct GNUNET_PeerIdentity)); + + + /* Copy all the elements from 0 to i into joined_trail. */ + for(k = 0; k < ( i+1); k++) + { + joined_trail[k] = trail_1[k]; + } + + /* Increment j as entry stored is same as entry stored at i*/ + j = j+1; + + /* Copy all the elements from j to trail_2_len-1 to joined trail.*/ + while(k <= (*joined_trail_len - 1)) + { + joined_trail[k] = trail_2[j]; + j++; + k++; + } + + return joined_trail; + } + } + + /* Here you should join the trails. */ + *joined_trail_len = trail_1_len + trail_2_len + 1; + joined_trail = GNUNET_malloc (*joined_trail_len * + sizeof(struct GNUNET_PeerIdentity)); + + + for(i = 0; i < trail_1_len;i++) + { + joined_trail[i] = trail_1[i]; + } + + joined_trail[i] = my_identity; + i++; + + for (j = 0; i < *joined_trail_len; i++,j++) + { + joined_trail[i] = trail_2[j]; + } + + return joined_trail; +} + + /** * Return the trail from source to my current predecessor. Check if source * is already part of the this trail, if yes then return the shorten trail. @@ -4422,68 +4696,72 @@ get_trail_src_to_curr_pred (struct GNUNET_PeerIdentity source_peer, struct GNUNET_PeerIdentity *trail_src_to_curr_pred; unsigned int trail_me_to_curr_pred_length; struct FingerInfo *current_predecessor; - unsigned int i; + int i; unsigned int j; + unsigned int len; current_predecessor = &finger_table[PREDECESSOR_FINGER_ID]; - trail_me_to_curr_pred = get_shortest_trail (current_predecessor, - &trail_me_to_curr_pred_length); - if ((trail_me_to_curr_pred_length == 1) && - (0 == GNUNET_CRYPTO_cmp_peer_identity (&source_peer, - &trail_me_to_curr_pred[0]))) - { - *trail_src_to_curr_pred_length = 0; - return NULL; - } - - /* Check if trail_me_to_curr_pred contains source. */ - if (trail_me_to_curr_pred_length > 1) + /* Check if trail_src_to_me contains current_predecessor. */ + for (i = 0; i < trail_src_to_me_len; i++) { - for(i = trail_me_to_curr_pred_length - 1; i > 0; i--) - { - if(0 != GNUNET_CRYPTO_cmp_peer_identity (&source_peer, - &trail_me_to_curr_pred[i])) - continue; + if (0 != GNUNET_CRYPTO_cmp_peer_identity(&trail_src_to_me[i], + ¤t_predecessor->finger_identity)) + continue; - i = i+1; - /* Source is the last element in the trail to reach to my pred. - Source is direct friend of the pred. */ - if (trail_me_to_curr_pred_length == i) - { - *trail_src_to_curr_pred_length = 0; - return NULL; - } - - - *trail_src_to_curr_pred_length = trail_me_to_curr_pred_length - i; - trail_src_to_curr_pred = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)* - *trail_src_to_curr_pred_length); - for(j = 0; j < *trail_src_to_curr_pred_length; i++,j++) - { - trail_src_to_curr_pred[j] = trail_me_to_curr_pred[i]; - } - return trail_src_to_curr_pred; - } + *trail_src_to_curr_pred_length = i; + + if(0 == i) + return NULL; + + trail_src_to_curr_pred = GNUNET_malloc (*trail_src_to_curr_pred_length * + sizeof(struct GNUNET_PeerIdentity)); + for (j = 0; j < i; j++) + trail_src_to_curr_pred[j] = trail_src_to_me[j]; + return trail_src_to_curr_pred; } - /* Append trail from source to me to my current_predecessor. */ - *trail_src_to_curr_pred_length = trail_src_to_me_len + - trail_me_to_curr_pred_length + 1; - trail_src_to_curr_pred = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)* - *trail_src_to_curr_pred_length); + trail_me_to_curr_pred = get_shortest_trail (current_predecessor, + &trail_me_to_curr_pred_length); + + /* Check if trail contains the source_peer. */ + for (i = trail_me_to_curr_pred_length - 1; i >= 0; i--) + { + if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source_peer, + &trail_me_to_curr_pred[i])) + continue; - for (i = 0; i < trail_src_to_me_len; i++) - trail_src_to_curr_pred[i] = trail_src_to_me[i]; + /* Source is NOT part of trail. */ + i++; - trail_src_to_curr_pred[i] = my_identity; - i++; + /* Source is the last element in the trail to reach to my pred. + Source is direct friend of the pred. */ + if (trail_me_to_curr_pred_length == i) + { + *trail_src_to_curr_pred_length = 0; + GNUNET_free_non_null (trail_me_to_curr_pred); + return NULL; + } + + *trail_src_to_curr_pred_length = trail_me_to_curr_pred_length - i; + trail_src_to_curr_pred = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)* + *trail_src_to_curr_pred_length); - for (j = 0; i < *trail_src_to_curr_pred_length; i++,j++) - trail_src_to_curr_pred[i] = trail_me_to_curr_pred[j]; + for (j = 0; j < *trail_src_to_curr_pred_length; i++,j++) + trail_src_to_curr_pred[j] = trail_me_to_curr_pred[i]; + GNUNET_free_non_null (trail_me_to_curr_pred); + return trail_src_to_curr_pred; + } + trail_src_to_curr_pred = check_for_duplicate_entries (trail_src_to_me, + trail_src_to_me_len, + trail_me_to_curr_pred, + trail_me_to_curr_pred_length, + &len); + *trail_src_to_curr_pred_length = len; + GNUNET_free_non_null(trail_me_to_curr_pred); return trail_src_to_curr_pred; } @@ -4511,19 +4789,23 @@ update_predecessor (struct GNUNET_PeerIdentity finger, &trail_to_new_predecessor_id, sizeof (trail_to_new_predecessor_id)); - /* Finger is a friend. */ - if (trail_length == 0) + if (0 == trail_length) { trail_to_new_predecessor = NULL; GDS_ROUTING_add (trail_to_new_predecessor_id, my_identity, finger); - GNUNET_assert (NULL != (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &finger))); + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger); + if (NULL == target_friend) + { + GNUNET_break (0); + return; + } } else { /* Invert the trail to get the trail from me to finger, NOT including the endpoints.*/ + GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap, + &trail[trail_length-1])); trail_to_new_predecessor = invert_trail (trail, trail_length); /* Add an entry in your routing table. */ @@ -4534,9 +4816,6 @@ update_predecessor (struct GNUNET_PeerIdentity finger, GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail_to_new_predecessor[0]))); - GNUNET_assert (NULL != ( - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &trail[trail_length - 1]))); } /* Add entry in routing table of all peers that are part of trail from me @@ -4550,7 +4829,7 @@ update_predecessor (struct GNUNET_PeerIdentity finger, add_new_finger (finger, trail_to_new_predecessor, trail_length, trail_to_new_predecessor_id, PREDECESSOR_FINGER_ID); - GNUNET_free_non_null (trail_to_new_predecessor); + GNUNET_free_non_null(trail_to_new_predecessor); } @@ -4570,12 +4849,11 @@ compare_and_update_predecessor (struct GNUNET_PeerIdentity finger, unsigned int trail_length) { struct FingerInfo *current_predecessor; - const struct GNUNET_PeerIdentity *closest_peer; + struct GNUNET_PeerIdentity closest_peer; uint64_t predecessor_value; unsigned int is_predecessor = 1; current_predecessor = &finger_table[PREDECESSOR_FINGER_ID]; - GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger, &my_identity)); /* No predecessor. Add finger as your predecessor. */ @@ -4584,9 +4862,7 @@ compare_and_update_predecessor (struct GNUNET_PeerIdentity finger, update_predecessor (finger, trail, trail_length); return; } - /* FIXME: Here we should first call find_successor and get a locally known - predecessor. If locally known predecessor is closest then current or finger, - add that as predecessor. */ + if (0 == GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor->finger_identity, &finger)) { @@ -4600,7 +4876,7 @@ compare_and_update_predecessor (struct GNUNET_PeerIdentity finger, /* Finger is the closest predecessor. Remove the existing one and add the new one. */ - if (closest_peer == &finger) + if (0 == GNUNET_CRYPTO_cmp_peer_identity(&closest_peer, &finger)) { remove_existing_finger (current_predecessor, PREDECESSOR_FINGER_ID); update_predecessor (finger, trail, trail_length); @@ -4628,12 +4904,12 @@ handle_dht_p2p_verify_successor(void *cls, struct GNUNET_PeerIdentity source_peer; struct GNUNET_PeerIdentity *trail; struct GNUNET_PeerIdentity *next_hop; - struct FingerInfo *current_predecessor; + struct FingerInfo current_predecessor; struct FriendInfo *target_friend; unsigned int trail_src_to_curr_pred_len = 0; struct GNUNET_PeerIdentity *trail_src_to_curr_pred; - size_t msize; unsigned int trail_length; + size_t msize; msize = ntohs (message->size); @@ -4653,22 +4929,24 @@ handle_dht_p2p_verify_successor(void *cls, return GNUNET_OK; } + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); + trail_id = vsm->trail_id; source_peer = vsm->source_peer; successor = vsm->successor; trail = (struct GNUNET_PeerIdentity *)&vsm[1]; - /* I am NOT the successor of source_peer. Pass the message to next_hop on * the trail. */ if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&successor, &my_identity))) { next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST); - if (NULL == next_hop) { - GNUNET_break_op (0); - return GNUNET_SYSERR; + return GNUNET_OK; } target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); @@ -4689,39 +4967,42 @@ handle_dht_p2p_verify_successor(void *cls, /* Check if the source_peer could be our predecessor and if yes then update * it. */ compare_and_update_predecessor (source_peer, trail, trail_length); - current_predecessor = &finger_table[PREDECESSOR_FINGER_ID]; + current_predecessor = finger_table[PREDECESSOR_FINGER_ID]; /* Is source of this message NOT my predecessor. */ - if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor->finger_identity, + if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor.finger_identity, &source_peer))) { - trail_src_to_curr_pred = get_trail_src_to_curr_pred (source_peer, - trail, - trail_length, - &trail_src_to_curr_pred_len); + trail_src_to_curr_pred = + get_trail_src_to_curr_pred (source_peer, + trail, + trail_length, + &trail_src_to_curr_pred_len); } else { trail_src_to_curr_pred_len = trail_length; - int i; - trail_src_to_curr_pred = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)*trail_length); + unsigned int i; + + trail_src_to_curr_pred = + GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity) + *trail_src_to_curr_pred_len); for(i = 0; i < trail_src_to_curr_pred_len; i++) { trail_src_to_curr_pred[i] = trail[i]; } - } - + GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))); GDS_NEIGHBOURS_send_verify_successor_result (source_peer, my_identity, - current_predecessor->finger_identity, + current_predecessor.finger_identity, trail_id, trail_src_to_curr_pred, trail_src_to_curr_pred_len, GDS_ROUTING_DEST_TO_SRC, target_friend); - + GNUNET_free_non_null(trail_src_to_curr_pred); return GNUNET_OK; } @@ -4765,28 +5046,39 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, &trail_me_to_probable_successor[i])) continue; - j = 0; *trail_to_new_successor_length = (trail_me_to_probable_successor_len - i); trail_to_new_successor = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)* *trail_to_new_successor_length); - for(j = 0;i < trail_me_to_probable_successor_len;i++,j++) + + for(j = 0; j < *trail_to_new_successor_length; i++,j++) { trail_to_new_successor[j] = trail_me_to_probable_successor[i]; } + return trail_to_new_successor; } } *trail_to_new_successor_length = trail_me_to_probable_successor_len; - trail_to_new_successor = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)* - *trail_to_new_successor_length); + return (struct GNUNET_PeerIdentity*)trail_me_to_probable_successor; +} + +// TODO: Move up +struct SendNotifyContext +{ + struct GNUNET_PeerIdentity source_peer; + struct GNUNET_PeerIdentity successor; + struct GNUNET_PeerIdentity *successor_trail; + unsigned int successor_trail_length; + struct GNUNET_HashCode succesor_trail_id; + struct FriendInfo *target_friend; + unsigned int num_retries_scheduled; +}; - for(i = 0; i < *trail_to_new_successor_length; i++) - trail_to_new_successor[i] = trail_me_to_probable_successor[i]; - return trail_to_new_successor; -} +void +send_notify_new_successor (void *cls); /** @@ -4795,10 +5087,14 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, * In case probable successor is the correct successor, remove the existing * successor. Add probable successor as new successor. Send notify new successor * message to new successor. - * @param curr_succ - * @param probable_successor - * @param trail - * @param trail_length + * @param curr_succ Peer to which we sent the verify successor message. It may + * or may not be our real current successor, as we may have few iterations of + * find finger trail task. + * @param probable_successor Peer which should be our successor accroding to @a + * curr_succ + * @param trail List of peers to reach from me to @a probable successor, NOT including + * endpoints. + * @param trail_length Total number of peers in @a trail. */ static void compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, @@ -4807,45 +5103,84 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, unsigned int trail_length) { struct FingerInfo *current_successor; - const struct GNUNET_PeerIdentity *closest_peer; + struct GNUNET_PeerIdentity closest_peer; struct GNUNET_HashCode trail_id; struct GNUNET_PeerIdentity *trail_me_to_probable_succ; struct FriendInfo *target_friend; unsigned int trail_me_to_probable_succ_len; - unsigned int is_predecessor = GNUNET_NO; + unsigned int is_predecessor = 0; uint64_t successor_value; current_successor = &finger_table[0]; successor_value = compute_finger_identity_value(0); - /* Have we found some other successor, while waiting for verify successor result - * - * FIXME closest_peer is being overwritten just after the if - */ -#if 0 - if(0 != GNUNET_CRYPTO_cmp_peer_identity(&curr_succ, ¤t_successor->finger_identity)) + /* If probable successor is same as current_successor, do nothing. */ + if(0 == GNUNET_CRYPTO_cmp_peer_identity (&probable_successor, + ¤t_successor->finger_identity)) { - /* We could have added this new successor, only if it was closer the old one. */ - closest_peer = select_closest_peer (&curr_succ, - ¤t_successor->finger_identity, - successor_value, is_predecessor); - - /* FIXME: it may fail in case we have done more number of iterations of - find _finger_trail_task. */ - /*GNUNET_assert (0 == - GNUNET_CRYPTO_cmp_peer_identity (closest_peer, - ¤t_successor->finger_identity));*/ - + if ((NULL != GDS_stats)) + { + char *my_id_str; + uint64_t succ; + char *key; + uint64_t my_id; + memcpy (&my_id, &my_identity, sizeof(uint64_t)); + my_id_str = GNUNET_strdup (GNUNET_i2s_full (&my_identity)); + memcpy(&succ, ¤t_successor->finger_identity, sizeof(uint64_t)); + succ = GNUNET_ntohll(succ); + GNUNET_asprintf (&key, "XDHT:%s:", my_id_str); + GNUNET_free (my_id_str); + + GNUNET_STATISTICS_set (GDS_stats, key, succ, 0); + GNUNET_free (key); + } + if (send_verify_successor_task == NULL) + send_verify_successor_task = + GNUNET_SCHEDULER_add_delayed(verify_successor_next_send_time, + &send_verify_successor_message, + NULL); + return; } -#endif - closest_peer = select_closest_peer (&probable_successor, ¤t_successor->finger_identity, successor_value, is_predecessor); /* If the current_successor in the finger table is closest, then do nothing. */ - if (closest_peer == ¤t_successor->finger_identity) + if (0 == GNUNET_CRYPTO_cmp_peer_identity (&closest_peer , + ¤t_successor->finger_identity)) + { + //FIXME: Is this a good place to return the stats. + if ((NULL != GDS_stats)) + { + char *my_id_str; + uint64_t succ; + char *key; + + my_id_str = GNUNET_strdup (GNUNET_i2s_full (&my_identity)); + memcpy(&succ, ¤t_successor->finger_identity, sizeof(uint64_t)); + GNUNET_asprintf (&key, "XDHT:%s:", my_id_str); + GNUNET_free (my_id_str); + GNUNET_STATISTICS_set (GDS_stats, key, succ, 0); + GNUNET_free (key); + } + + if(0 == successor_times) + { +// successor_times = 3; + verify_successor_next_send_time = + GNUNET_TIME_STD_BACKOFF (verify_successor_next_send_time); + } + else + successor_times--; + + + if (send_verify_successor_task == NULL) + send_verify_successor_task = + GNUNET_SCHEDULER_add_delayed(verify_successor_next_send_time, + &send_verify_successor_message, + NULL); return; + } /* Probable successor is the closest peer.*/ if(trail_length > 0) @@ -4858,9 +5193,8 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap, &probable_successor)); } - + trail_me_to_probable_succ_len = 0; - /* TODO: Check if the path to reach to probable successor contains a friend. */ trail_me_to_probable_succ = check_trail_me_to_probable_succ (probable_successor, trail, trail_length, @@ -4868,9 +5202,6 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, /* Remove the existing successor. */ remove_existing_finger (current_successor, 0); - - /* TODO URGENT: Check if any peer is present more than once, if yes then shorten - the trail. before sending it across the network. */ /* Generate a new trail id to reach to your new successor. */ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, &trail_id, sizeof (trail_id)); @@ -4889,24 +5220,66 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &probable_successor))); + &probable_successor))); } add_new_finger (probable_successor, trail_me_to_probable_succ, trail_me_to_probable_succ_len, trail_id, 0); - GDS_NEIGHBOURS_send_notify_new_successor (my_identity, probable_successor, - trail_me_to_probable_succ, - trail_me_to_probable_succ_len, - trail_id, - target_friend); - return; + struct SendNotifyContext *notify_ctx; + + notify_ctx = GNUNET_new(struct SendNotifyContext); + + notify_ctx->source_peer = my_identity; + notify_ctx->successor = probable_successor; + notify_ctx->successor_trail = + GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity) * trail_me_to_probable_succ_len); + memcpy(notify_ctx->successor_trail, trail_me_to_probable_succ, + sizeof(struct GNUNET_PeerIdentity) * trail_me_to_probable_succ_len); + notify_ctx->successor_trail_length = trail_me_to_probable_succ_len; + notify_ctx->succesor_trail_id = trail_id; + notify_ctx->target_friend = target_friend; + notify_ctx->num_retries_scheduled = 0; + GNUNET_free_non_null (trail_me_to_probable_succ); + + // TODO: Check if we should verify before schedule if already scheduled. + GNUNET_SCHEDULER_add_now(&send_notify_new_successor, (void*)notify_ctx); } + +void +send_notify_new_successor (void *cls) +{ + struct SendNotifyContext *ctx = cls; + + GDS_NEIGHBOURS_send_notify_new_successor (ctx->source_peer, + ctx->successor, + ctx->successor_trail, + ctx->successor_trail_length, + ctx->succesor_trail_id, + ctx->target_friend); + + if (0 == ctx->num_retries_scheduled && + send_notify_new_successor_retry_task != NULL) + { + // Result from previous notify successos hasn't arrived, so the retry task + // hasn't been cancelled! Already a new notify successor must be called. + // We will cancel the retry request. + struct SendNotifyContext *old_notify_ctx; + old_notify_ctx = GNUNET_SCHEDULER_cancel(send_notify_new_successor_retry_task); + GNUNET_free (old_notify_ctx->successor_trail); + GNUNET_free (old_notify_ctx); + send_notify_new_successor_retry_task = NULL; + } + + ctx->num_retries_scheduled++; + send_notify_new_successor_retry_task = GNUNET_SCHEDULER_add_delayed(notify_successor_retry_time, + &send_notify_new_successor, + cls); +} + /* - * FIXME: Check for duplicate elements everywhere when you are making - * trails. * Core handle for p2p verify successor result messages. * @param cls closure * @param message message @@ -4931,8 +5304,6 @@ handle_dht_p2p_verify_successor_result(void *cls, size_t msize; msize = ntohs (message->size); - /* We send a trail to reach from old successor to new successor, if - * old_successor != new_successor.*/ if (msize < sizeof (struct PeerVerifySuccessorResultMessage)) { GNUNET_break_op (0); @@ -4940,15 +5311,19 @@ handle_dht_p2p_verify_successor_result(void *cls, } vsrm = (const struct PeerVerifySuccessorResultMessage *) message; - trail_length = (msize - sizeof (struct PeerVerifySuccessorResultMessage))/ - sizeof (struct GNUNET_PeerIdentity); - if ((msize - sizeof (struct PeerVerifySuccessorResultMessage)) % sizeof (struct GNUNET_PeerIdentity) != 0) { GNUNET_break_op (0); return GNUNET_OK; } + trail_length = (msize - sizeof (struct PeerVerifySuccessorResultMessage))/ + sizeof (struct GNUNET_PeerIdentity); + + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); trail = (const struct GNUNET_PeerIdentity *) &vsrm[1]; querying_peer = vsrm->querying_peer; @@ -4960,17 +5335,38 @@ handle_dht_p2p_verify_successor_result(void *cls, /* I am the querying_peer. */ if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity))) { + /* Cancel Retry Task */ + if (NULL != send_verify_successor_retry_task) + { + struct VerifySuccessorContext *ctx; + ctx = GNUNET_SCHEDULER_cancel(send_verify_successor_retry_task); + GNUNET_free(ctx); + send_verify_successor_retry_task = NULL; + } compare_and_update_successor (current_successor, probable_successor, trail, trail_length); return GNUNET_OK; } - + /*If you are not the querying peer then pass on the message */ - GNUNET_assert (NULL != (next_hop = - GDS_ROUTING_get_next_hop (trail_id, trail_direction))); - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop))); + if(NULL == (next_hop = + GDS_ROUTING_get_next_hop (trail_id, trail_direction))) + { + /* Here it may happen that source peer has found a new successor, and removed + the trail, Hence no entry found in the routing table. Fail silently.*/ + DEBUG (" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line %u", + GNUNET_i2s (&my_identity), + GNUNET_h2s (&trail_id), + __LINE__); + GNUNET_break_op(0); + return GNUNET_OK; + } + if (NULL == (target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop))) + { + GNUNET_break_op(0); + return GNUNET_OK; + } GDS_NEIGHBOURS_send_verify_successor_result (querying_peer, vsrm->current_successor, probable_successor, trail_id, @@ -5005,36 +5401,45 @@ handle_dht_p2p_notify_new_successor(void *cls, uint32_t trail_length; msize = ntohs (message->size); - - /* We have the trail to reach from source to new successor. */ if (msize < sizeof (struct PeerNotifyNewSuccessorMessage)) { GNUNET_break_op (0); return GNUNET_YES; } - nsm = (const struct PeerNotifyNewSuccessorMessage *) message; - trail_length = (msize - sizeof (struct PeerNotifyNewSuccessorMessage))/ - sizeof (struct GNUNET_PeerIdentity); if ((msize - sizeof (struct PeerNotifyNewSuccessorMessage)) % sizeof (struct GNUNET_PeerIdentity) != 0) { GNUNET_break_op (0); return GNUNET_OK; } + trail_length = (msize - sizeof (struct PeerNotifyNewSuccessorMessage))/ + sizeof (struct GNUNET_PeerIdentity); + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); trail = (struct GNUNET_PeerIdentity *) &nsm[1]; source = nsm->source_peer; new_successor = nsm->new_successor; trail_id = nsm->trail_id; - //FIXME: add a check to make sure peer is correct. - /* I am the new_successor to source_peer. */ if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_successor)) { - GDS_ROUTING_add (trail_id, *peer, my_identity); + if(trail_length > 0) + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail[trail_length - 1], + peer)); + else + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&source, peer)); + compare_and_update_predecessor (source, trail, trail_length); + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer); + GNUNET_assert (NULL != target_friend); + GDS_NEIGHBOURS_send_notify_succcessor_confirmation (trail_id, + GDS_ROUTING_DEST_TO_SRC, + target_friend); return GNUNET_OK; } @@ -5043,22 +5448,29 @@ handle_dht_p2p_notify_new_successor(void *cls, my_index = search_my_index (trail, trail_length); if (-1 == my_index) { + DEBUG ("No entry found in trail\n"); + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if((trail_length + 1) == my_index) + { + DEBUG ("Found twice in trail.\n"); GNUNET_break_op (0); return GNUNET_SYSERR; } - if ((trail_length-1) == my_index) next_hop = new_successor; else next_hop = trail[my_index + 1]; - - /* Add an entry in routing table for trail from source to its new successor. */ - GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop)); - - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop))); + GDS_ROUTING_add(trail_id, *peer, next_hop); + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop); + if (NULL == target_friend) + { + GNUNET_break(0); + return GNUNET_OK; + } GDS_NEIGHBOURS_send_notify_new_successor (source, new_successor, trail, trail_length, trail_id, target_friend); @@ -5067,6 +5479,97 @@ handle_dht_p2p_notify_new_successor(void *cls, } +/** + * Core handler for P2P notify successor message + * @param cls closure + * @param message message + * @param peer peer identity this notification is about + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +handle_dht_p2p_notify_succ_confirmation (void *cls, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + const struct PeerNotifyConfirmationMessage *notify_confirmation; + enum GDS_ROUTING_trail_direction trail_direction; + struct GNUNET_HashCode trail_id; + struct FriendInfo *target_friend; + struct GNUNET_PeerIdentity *next_hop; + size_t msize; + + msize = ntohs (message->size); + + if (msize != sizeof (struct PeerNotifyConfirmationMessage)) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); + + notify_confirmation = (const struct PeerNotifyConfirmationMessage *) message; + trail_direction = ntohl (notify_confirmation->trail_direction); + trail_id = notify_confirmation->trail_id; + + next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction); + if (NULL == next_hop) + { + /* The source of notify new successor, might have found even a better + successor. In that case it send a trail teardown message, and hence, + the next hop is NULL. */ + //Fixme: Add some print to confirm the above theory. + return GNUNET_OK; + } + + /* I peer which sent the notify successor message to the successor. */ + if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)) + { + /* + * Schedule another round of verify sucessor with your current successor + * which may or may not be source of this message. This message is used + * only to ensure that we have a path setup to reach to our successor. + */ + + // TODO: cancel schedule of notify_successor_retry_task + if (send_notify_new_successor_retry_task != NULL) + { + struct SendNotifyContext *notify_ctx; + notify_ctx = GNUNET_SCHEDULER_cancel(send_notify_new_successor_retry_task); + GNUNET_free (notify_ctx->successor_trail); + GNUNET_free (notify_ctx); + send_notify_new_successor_retry_task = NULL; + } + if (send_verify_successor_task == NULL) + { + verify_successor_next_send_time.rel_value_us = + DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us); + send_verify_successor_task = + GNUNET_SCHEDULER_add_delayed(verify_successor_next_send_time, + &send_verify_successor_message, + NULL); + } + } + else + { + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); + if (NULL == target_friend) + { + DEBUG ("\n friend not found, line number = %d",__LINE__); + return GNUNET_SYSERR; + } + GDS_NEIGHBOURS_send_notify_succcessor_confirmation (trail_id, + GDS_ROUTING_DEST_TO_SRC, + target_friend); + } + return GNUNET_OK; +} + + /** * Core handler for P2P trail rejection message * @param cls closure @@ -5087,28 +5590,29 @@ handle_dht_p2p_trail_setup_rejection (void *cls, struct GNUNET_HashCode trail_id; struct GNUNET_PeerIdentity next_peer; struct GNUNET_PeerIdentity source; - struct GNUNET_PeerIdentity *next_hop; uint64_t ultimate_destination_finger_value; unsigned int is_predecessor; size_t msize; msize = ntohs (message->size); - /* We are passing the trail setup so far. */ if (msize < sizeof (struct PeerTrailRejectionMessage)) { GNUNET_break_op (0); return GNUNET_YES; } - trail_rejection = (const struct PeerTrailRejectionMessage *) message; - trail_length = (msize - sizeof (struct PeerTrailRejectionMessage))/ - sizeof (struct GNUNET_PeerIdentity); if ((msize - sizeof (struct PeerTrailRejectionMessage)) % sizeof (struct GNUNET_PeerIdentity) != 0) { GNUNET_break_op (0); return GNUNET_OK; } + trail_length = (msize - sizeof (struct PeerTrailRejectionMessage))/ + sizeof (struct GNUNET_PeerIdentity); + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_rejection[1]; is_predecessor = ntohl (trail_rejection->is_predecessor); @@ -5117,11 +5621,14 @@ handle_dht_p2p_trail_setup_rejection (void *cls, trail_id = trail_rejection->trail_id; ultimate_destination_finger_value = GNUNET_ntohll (trail_rejection->ultimate_destination_finger_value); - /* First set the congestion time of the friend that sent you this message. */ - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))); + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer); + if (NULL == target_friend) + { + DEBUG ("\nLINE = %d ,No friend found.",__LINE__); + GNUNET_break(0); + return GNUNET_OK; + } target_friend->congestion_timestamp = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), congestion_timeout); @@ -5134,78 +5641,85 @@ handle_dht_p2p_trail_setup_rejection (void *cls, /* If I am congested then pass this message to peer before me in trail. */ if(GNUNET_YES == GDS_ROUTING_threshold_reached()) { - struct GNUNET_PeerIdentity *new_trail; - unsigned int new_trail_length; + /* First remove yourself from the trail. */ + unsigned int new_trail_length = trail_length - 1; + struct GNUNET_PeerIdentity trail[new_trail_length]; - /* Remove yourself from the trail setup so far. */ - if (trail_length == 1) - { - new_trail = NULL; - new_trail_length = 0; - next_hop = &source; - } + memcpy (trail, trail_peer_list, new_trail_length * sizeof(struct GNUNET_PeerIdentity)); + if (0 == trail_length) + next_peer = source; else - { - memcpy (&next_hop , &trail_peer_list[trail_length - 2], - sizeof (struct GNUNET_PeerIdentity)); + next_peer = trail[new_trail_length-1]; - /* Remove myself from the trail. */ - new_trail_length = trail_length -1; - new_trail = GNUNET_malloc (new_trail_length * sizeof (struct GNUNET_PeerIdentity)); - memcpy (new_trail, trail_peer_list, new_trail_length * sizeof (struct GNUNET_PeerIdentity)); + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer); + if (NULL == target_friend) + { + DEBUG ("\nLINE = %d ,No friend found.",__LINE__); + GNUNET_break(0); + return GNUNET_OK; } - - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop))); GDS_NEIGHBOURS_send_trail_rejection (source, ultimate_destination_finger_value, my_identity, is_predecessor, - new_trail,new_trail_length,trail_id, + trail, new_trail_length, trail_id, target_friend, CONGESTION_TIMEOUT); - GNUNET_free (new_trail); return GNUNET_OK; } struct Closest_Peer successor; - successor = find_successor (ultimate_destination_finger_value, is_predecessor); + successor = find_local_best_known_next_hop (ultimate_destination_finger_value, is_predecessor); /* Am I the final destination? */ if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination, &my_identity))) { - if (0 == trail_length) + /*Here you are already part of trail. Copy the trail removing yourself. */ + unsigned int new_trail_length = trail_length - 1; + struct GNUNET_PeerIdentity trail[new_trail_length]; + + memcpy (trail, trail_peer_list, new_trail_length * sizeof(struct GNUNET_PeerIdentity)); + + if (0 == new_trail_length) next_peer = source; else - next_peer = trail_peer_list[trail_length-1]; - - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer))); + { + next_peer = trail[new_trail_length-1]; + } + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer); + if (NULL == target_friend) + { + DEBUG ("\nLINE = %d ,No friend found.",__LINE__); + GNUNET_break(0); + return GNUNET_OK; + } GDS_NEIGHBOURS_send_trail_setup_result (source, my_identity, - target_friend, trail_length, - trail_peer_list, + target_friend, new_trail_length, + trail, is_predecessor, ultimate_destination_finger_value, trail_id); } else { - struct GNUNET_PeerIdentity peer_list[trail_length + 1]; - - memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); - peer_list[trail_length] = my_identity; - - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop))); + /* Here I was already part of trail. So no need to add. */ + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, + &successor.next_hop); + if (NULL == target_friend) + { + DEBUG ("\nLINE = %d ,No friend found.",__LINE__); + GNUNET_break(0); + return GNUNET_OK; + } GDS_NEIGHBOURS_send_trail_setup (source, ultimate_destination_finger_value, successor.best_known_destination, - target_friend, trail_length + 1, peer_list, + target_friend, trail_length, trail_peer_list, is_predecessor, trail_id, successor.trail_id); } @@ -5213,72 +5727,6 @@ handle_dht_p2p_trail_setup_rejection (void *cls, } -/* - * Core handle for p2p trail tear compression messages. - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -handle_dht_p2p_trail_compression (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - const struct PeerTrailCompressionMessage *trail_compression; - struct GNUNET_PeerIdentity *next_hop; - struct FriendInfo *target_friend; - struct GNUNET_HashCode trail_id; - size_t msize; - - msize = ntohs (message->size); - - if (msize != sizeof (struct PeerTrailCompressionMessage)) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - trail_compression = (const struct PeerTrailCompressionMessage *) message; - trail_id = trail_compression->trail_id; - - /* Am I the new first friend to reach to finger of this trail. */ - if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&trail_compression->new_first_friend, - &my_identity))) - { - GNUNET_assert (NULL != - (GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &trail_compression->source_peer))); - - /* Update your prev hop to source of this message. */ - GNUNET_assert (GNUNET_SYSERR != - (GDS_ROUTING_update_trail_prev_hop (trail_id, - trail_compression->source_peer))); - return GNUNET_OK; - } - - /* Pass the message to next hop to finally reach to new_first_friend. */ - next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST); - - if (NULL == next_hop) - { - GNUNET_break (0); - return GNUNET_OK; - } - - GNUNET_assert (NULL != - (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop))); - - GDS_ROUTING_remove_trail (trail_id); - - GDS_NEIGHBOURS_send_trail_compression (trail_compression->source_peer, - trail_id, - trail_compression->new_first_friend, - target_friend); - return GNUNET_OK; -} - - /** * Core handler for trail teardown message. * @param cls closure @@ -5305,6 +5753,11 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer return GNUNET_OK; } + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); + trail_teardown = (const struct PeerTrailTearDownMessage *) message; trail_direction = ntohl (trail_teardown->trail_direction); trail_id = trail_teardown->trail_id; @@ -5322,9 +5775,12 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer #endif next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction); - if (NULL == next_hop) { + DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line %u", + GNUNET_i2s (&my_identity), + GNUNET_h2s(&trail_id), + __LINE__); GNUNET_break (0); return GNUNET_SYSERR; } @@ -5340,7 +5796,7 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer /* If not final destination, then send a trail teardown message to next hop.*/ GNUNET_assert (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)); GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id)); - GDS_NEIGHBOURS_send_trail_teardown (trail_id, trail_direction, *next_hop); + GDS_NEIGHBOURS_send_trail_teardown (&trail_id, trail_direction, next_hop); } return GNUNET_OK; @@ -5388,15 +5844,16 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Bytes received from other peers"), msize, + GNUNET_NO); + trail = (const struct GNUNET_PeerIdentity *)&add_trail[1]; destination_peer = add_trail->destination_peer; source_peer = add_trail->source_peer; trail_id = add_trail->trail_id; - //FIXME: add a check that sender peer is not malicious. Make it a generic - // function so that it can be used in all other functions where we need the - // same functionality. - /* I am not the destination of the trail. */ if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &destination_peer)) { @@ -5406,12 +5863,15 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, my_index = search_my_index (trail, trail_length); if (-1 == my_index) { - GNUNET_break_op (0); return GNUNET_SYSERR; } - - + if((trail_length + 1) == my_index) + { + DEBUG ("Found twice in trail.\n"); + GNUNET_break_op (0); + return GNUNET_SYSERR; + } if ((trail_length - 1) == my_index) { next_hop = destination_peer; @@ -5420,9 +5880,9 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, { next_hop = trail[my_index + 1]; } - /* Add in your routing table. */ - GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer)); + GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop)); + //GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer)); GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop))); @@ -5448,55 +5908,45 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, */ static int remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend, - struct FingerInfo *remove_finger) + struct FingerInfo *finger) { - unsigned int matching_trails_count; + struct GNUNET_PeerIdentity *next_hop; + struct FriendInfo *remove_friend; + struct Trail *current_trail; + unsigned int matching_trails_count = 0; int i; - /* Number of trails with disconnected_friend as the first hop in the trail - * to reach from me to remove_finger, NOT including endpoints. */ - matching_trails_count = 0; - /* Iterate over all the trails of finger. */ - for (i = 0; i < remove_finger->trails_count; i++) + for (i = 0; i < finger->trails_count; i++) { - struct Trail *trail; - trail = &remove_finger->trail_list[i]; - - /* This assertion is ensure that there are no gaps in the trail list. - REMOVE IT AFTERWARDS. */ - GNUNET_assert (GNUNET_YES == trail->is_present); + current_trail = &finger->trail_list[i]; + if (GNUNET_NO == current_trail->is_present) + continue; /* First friend to reach to finger is disconnected_peer. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&trail->trail_head->peer, + if (0 == GNUNET_CRYPTO_cmp_peer_identity (¤t_trail->trail_head->peer, disconnected_friend)) { - struct GNUNET_PeerIdentity *next_hop; - struct FriendInfo *remove_friend; - - GNUNET_assert (NULL != - (remove_friend = + remove_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, - disconnected_friend))); - /* FIXME: removing no but check it. */ - //remove_friend->trails_count--; - next_hop = GDS_ROUTING_get_next_hop (trail->trail_id, + disconnected_friend); + GNUNET_assert (NULL != remove_friend); + next_hop = GDS_ROUTING_get_next_hop (current_trail->trail_id, GDS_ROUTING_SRC_TO_DEST); /* Here it may happen that as all the peers got disconnected, the entry in routing table for that particular trail has been removed, because the previously disconnected peer was either a next hop or prev hop of that peer. */ - if (NULL == next_hop) - continue; - - GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend, - next_hop))); + if (NULL != next_hop) + { + GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend, + next_hop))); + GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (current_trail->trail_id)); + } matching_trails_count++; - GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id)); - - free_trail (trail); - trail->is_present = GNUNET_NO; + free_trail (current_trail); + current_trail->is_present = GNUNET_NO; } } return matching_trails_count; @@ -5518,74 +5968,42 @@ remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend, static void remove_matching_fingers (const struct GNUNET_PeerIdentity *disconnected_peer) { - struct FingerInfo *remove_finger; - struct FriendInfo *remove_friend; + struct FingerInfo *current_finger; int removed_trails_count; int i; /* Iterate over finger table entries. */ for (i = 0; i < MAX_FINGERS; i++) { - remove_finger = &finger_table[i]; - - /* No finger stored at this trail index. */ - if (GNUNET_NO == remove_finger->is_present) - continue; + current_finger = &finger_table[i]; - /* I am my own finger, then ignore this finger. */ - if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_finger->finger_identity, - &my_identity)) + /* No finger stored at this trail index or I am the finger. */ + if ((GNUNET_NO == current_finger->is_present) || + (0 == GNUNET_CRYPTO_cmp_peer_identity (¤t_finger->finger_identity, + &my_identity))) continue; /* Is disconnected_peer a finger? */ if (0 == GNUNET_CRYPTO_cmp_peer_identity (disconnected_peer, - &remove_finger->finger_identity)) + ¤t_finger->finger_identity)) { - struct GNUNET_PeerIdentity *next_hop; - struct GNUNET_HashCode trail_id; - - - GNUNET_assert (GNUNET_YES == (remove_finger->trail_list[0].is_present)); - trail_id = remove_finger->trail_list[0].trail_id; - - if(NULL != - (next_hop = - GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST))) - { - GNUNET_assert (0 == - (GNUNET_CRYPTO_cmp_peer_identity (next_hop, - &remove_finger->finger_identity))); - GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id)); - GNUNET_assert (NULL != - (remove_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, - disconnected_peer))); - } - - remove_finger->trail_list[0].is_present = GNUNET_NO; - //GNUNET_assert (0 != remove_friend->trails_count); - //remove_friend->trails_count--; //FIXME; CHECK WHY IT FAILS AND THEN UNCOMMENT. - remove_finger->is_present = GNUNET_NO; - memset ((void *)&finger_table[i], 0, sizeof (finger_table[i])); - continue; + remove_existing_finger (current_finger, i); } /* If finger is a friend but not disconnected_friend, then continue. */ if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, - &remove_finger->finger_identity)) + ¤t_finger->finger_identity)) continue; /* Iterate over the list of trails to reach remove_finger. Check if * disconnected_friend is the first friend in any of the trail. */ removed_trails_count = remove_matching_trails (disconnected_peer, - remove_finger); - remove_finger->trails_count = - remove_finger->trails_count - removed_trails_count; - /* All the finger trails had disconnected_friend as the first friend, - * so free the finger. */ - if (remove_finger->trails_count == 0) + current_finger); + current_finger->trails_count = + current_finger->trails_count - removed_trails_count; + if (0 == current_finger->trails_count) { - remove_finger->is_present = GNUNET_NO; + current_finger->is_present = GNUNET_NO; memset ((void *)&finger_table[i], 0, sizeof (finger_table[i])); } } @@ -5603,41 +6021,58 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct FriendInfo *remove_friend; + struct P2PPendingMessage *pos; + unsigned int discarded; /* If disconnected to own identity, then return. */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; - GNUNET_assert (NULL != (remove_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))); + if(NULL == (remove_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))) + { + DEBUG("\n friend already disconnected."); + return; + } - /* Remove fingers with peer as first friend or if peer is a finger. */ remove_matching_fingers (peer); - - /* Remove any trail from routing table of which peer is a part of. This function - * internally sends a trail teardown message in the direction of which - * disconnected peer is not part of. */ GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer)); - - //GNUNET_assert (0 == remove_friend->trails_count); //FIXME; why should this fai. - - /* Remove peer from friend_peermap. */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (friend_peermap, peer, remove_friend)); + /* Remove all the messages queued in pending list of this peer is discarded.*/ + if (remove_friend->th != NULL) + { + GNUNET_CORE_notify_transmit_ready_cancel(remove_friend->th); + remove_friend->th = NULL; + } + + discarded = 0; + while (NULL != (pos = remove_friend->head)) + { + GNUNET_CONTAINER_DLL_remove (remove_friend->head, remove_friend->tail, pos); + discarded++; + GNUNET_free (pos); + } + + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop + ("# Queued messages discarded (peer disconnected)"), + discarded, GNUNET_NO); + //GNUNET_free (remove_friend); + if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap)) return; - if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task) + if (NULL != find_finger_trail_task) { GNUNET_SCHEDULER_cancel (find_finger_trail_task); - find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK; + find_finger_trail_task = NULL; } else GNUNET_break (0); - } @@ -5656,8 +6091,6 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity) if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity))) return; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity)); - /* If peer already exists in our friend_peermap, then exit. */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity)) @@ -5666,9 +6099,6 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity) return; } - GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1, - GNUNET_NO); - friend = GNUNET_new (struct FriendInfo); friend->id = *peer_identity; @@ -5677,14 +6107,13 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity) peer_identity, friend, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - - /* got a first connection, good time to start with FIND FINGER TRAIL requests...*/ - if (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task) + /* FIXME: now we are not making a distinction between fingers which are friends + * also.But later, we should add a congestion timestamp on the friend, so that it is + * selected after some time out. This is to ensure that both peers have added + * each other as their friend. */ + /* Got a first connection, good time to start with FIND FINGER TRAIL requests...*/ + if (NULL == find_finger_trail_task) { - next_send_time.rel_value_us = - DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us); find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL); } } @@ -5701,13 +6130,6 @@ core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { my_identity = *identity; - - uint64_t my_id64; - memcpy (&my_id64, &my_identity, sizeof (uint64_t)); - my_id64 = GNUNET_ntohll (my_id64); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "my_indentity = %s, my_id64=%llu\n",GNUNET_i2s(&my_identity),(unsigned long long)my_id64); - } @@ -5738,28 +6160,76 @@ GDS_NEIGHBOURS_init (void) {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT, 0}, {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR, 0}, {&handle_dht_p2p_trail_setup_rejection, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION, 0}, - {&handle_dht_p2p_trail_compression, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_COMPRESSION, - sizeof (struct PeerTrailCompressionMessage)}, {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN, sizeof (struct PeerTrailTearDownMessage)}, {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL, 0}, + {&handle_dht_p2p_notify_succ_confirmation, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION, + sizeof (struct PeerNotifyConfirmationMessage)}, {NULL, 0, 0} }; +#if ENABLE_MALICIOUS + act_malicious = 0; +#endif + core_api = GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, &handle_core_disconnect, NULL, GNUNET_NO, NULL, GNUNET_NO, core_handlers); + if (NULL == core_api) return GNUNET_SYSERR; + //TODO: check size of this peer map? friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); finger_table_init (); + successor_times = 10; + fingers_round_count = 5; + find_finger_trail_task_next_send_time.rel_value_us = + DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us); + + verify_successor_next_send_time.rel_value_us = + DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us); + + verify_successor_retry_time.rel_value_us = + DHT_SEND_VERIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + DHT_SEND_VERIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us); + + notify_successor_retry_time.rel_value_us = + DHT_SEND_NOTIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + DHT_SEND_NOTIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us); + return GNUNET_OK; } +/** + * Free the memory held up by trails of a finger. + */ +static void +delete_finger_table_entries() +{ + unsigned int i; + unsigned int j; + + for(i = 0; i < MAX_FINGERS; i++) + { + if(GNUNET_YES == finger_table[i].is_present) + { + for(j = 0; j < finger_table[i].trails_count; j++) + free_trail(&finger_table[i].trail_list[j]); + } + } +} + + /** * Shutdown neighbours subsystem. */ @@ -5772,21 +6242,38 @@ GDS_NEIGHBOURS_done (void) GNUNET_CORE_disconnect (core_api); core_api = NULL; + delete_finger_table_entries(); GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap)); GNUNET_CONTAINER_multipeermap_destroy (friend_peermap); friend_peermap = NULL; - if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task) + if (NULL != find_finger_trail_task) { - GNUNET_break (0); GNUNET_SCHEDULER_cancel (find_finger_trail_task); - find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK; + find_finger_trail_task = NULL; } - if (GNUNET_SCHEDULER_NO_TASK != send_verify_successor_task) + if (NULL != send_verify_successor_task) { GNUNET_SCHEDULER_cancel (send_verify_successor_task); - send_verify_successor_task = GNUNET_SCHEDULER_NO_TASK; + send_verify_successor_task = NULL; + } + + if (NULL != send_verify_successor_retry_task) + { + struct VerifySuccessorContext *ctx; + ctx = GNUNET_SCHEDULER_cancel (send_verify_successor_retry_task); + GNUNET_free(ctx); + send_verify_successor_retry_task = NULL; + } + + if (send_notify_new_successor_retry_task != NULL) + { + struct SendNotifyContext *notify_ctx; + notify_ctx = GNUNET_SCHEDULER_cancel(send_notify_new_successor_retry_task); + GNUNET_free (notify_ctx->successor_trail); + GNUNET_free (notify_ctx); + send_notify_new_successor_retry_task = NULL; } }