X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fdht%2Fgnunet-service-xdht_neighbours.c;h=6f3137f8a4b47d90b4191757558930ae7f27b29b;hb=3b680a20ab2cbb98cfa658d85be7a44baaf95d2c;hp=f0a1cb8b9987fc2df040ecf28cb53919dc9ee3fc;hpb=1c566a6cf35df66afb22b9516e408b2fdc2ff85d;p=oweals%2Fgnunet.git diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c index f0a1cb8b9..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,13 +51,6 @@ * hashing. */ - -/** - * FIXME: URGENT - * We should have a message type like notify successor result. only when - * this message is being recvied by the new successor. we should schedule - * another round of verify successor. - */ #define DEBUG(...) \ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) @@ -80,7 +72,17 @@ /** * How long to wait before sending another verify successor message. */ -#define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 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 ? @@ -94,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. */ @@ -102,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. @@ -281,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. @@ -498,6 +501,27 @@ struct PeerNotifyNewSuccessorMessage */ }; +/** + * P2P Notify Successor Confirmation message. + */ +struct PeerNotifyConfirmationMessage +{ + /** + * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier of the trail. + */ + struct GNUNET_HashCode trail_id; + + /** + * Direction of trail. + */ + uint32_t trail_direction; +}; + /** * P2P Trail Tear Down message. @@ -598,6 +622,7 @@ struct PeerAddTrailMessage */ }; + GNUNET_NETWORK_STRUCT_END /** @@ -660,7 +685,7 @@ 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. @@ -741,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. */ @@ -798,27 +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. + * of finger table index. */ unsigned int finger_table_index; }; +/** + * Context for send_verify_successor_task. + */ +struct VerifySuccessorContext +{ + /** + * Number of times this has been scheduled. + */ + 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 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 GNUNET_SCHEDULER_TaskIdentifier send_verify_successor_task; +static struct GNUNET_SCHEDULER_Task * send_notify_new_successor_retry_task; /** * Identity of this peer. @@ -854,15 +907,31 @@ static struct GNUNET_CORE_Handle *core_api; static unsigned int current_search_finger_index; /** - * Time duration to schedule find finger trail task. + * 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. + * 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? @@ -870,18 +939,26 @@ static struct GNUNET_TIME_Relative verify_successor_next_send_time; unsigned int track_topology; /** - * Should I be a malicious peer and drop the PUT/GET packets? + * 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. + * 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. @@ -901,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) @@ -931,7 +1015,8 @@ core_transmit_notify (void *cls, size_t size, void *buf) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop - ("# Bytes transmitted to other peers"), msize, + ("# Bytes transmitted to other peers"), + msize, GNUNET_NO); memcpy (&cbuf[off], pending->msg, msize); off += msize; @@ -971,7 +1056,7 @@ process_friend_queue (struct FriendInfo *peer) { return; } - + peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, pending->importance, @@ -988,10 +1073,11 @@ process_friend_queue (struct FriendInfo *peer) * Set the ENABLE_MALICIOUS value to malicious. * @param malicious */ -void +int GDS_NEIGHBOURS_act_malicious (unsigned int malicious) { act_malicious = malicious; + return GNUNET_OK; } #endif @@ -1054,7 +1140,7 @@ GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer, tsm->is_predecessor = htonl (is_predecessor); tsm->trail_id = trail_id; tsm->intermediate_trail_id = intermediate_trail_id; - + if (trail_length > 0) { peer_list = (struct GNUNET_PeerIdentity *) &tsm[1]; @@ -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 (PENDING_MESSAGE_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); @@ -1127,7 +1213,51 @@ GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer 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. */ + GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); + target_friend->pending_count++; + 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++; @@ -1236,7 +1366,7 @@ GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_ msize = sizeof (struct PeerVerifySuccessorMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); - + if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); @@ -1275,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; @@ -1290,17 +1421,19 @@ GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id, size_t msize; msize = sizeof (struct PeerTrailTearDownMessage); - 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) { @@ -1315,7 +1448,7 @@ GDS_NEIGHBOURS_send_trail_teardown (struct GNUNET_HashCode trail_id, 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. */ @@ -1381,10 +1514,10 @@ GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying vsmr->current_successor = current_successor; vsmr->probable_successor = probable_successor; vsmr->trail_direction = htonl (trail_direction); - vsmr->trail_id = trail_id; + vsmr->trail_id = trail_id; 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); target_friend->pending_count++; @@ -1431,7 +1564,7 @@ GDS_NEIGHBOURS_send_notify_new_successor (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->importance = 0; /* FIXME */ pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); @@ -1445,7 +1578,7 @@ GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer 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); target_friend->pending_count++; @@ -1504,7 +1637,7 @@ 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++; @@ -1528,7 +1661,7 @@ search_my_index (const struct GNUNET_PeerIdentity *trail, 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])) @@ -1577,7 +1710,7 @@ is_friend_congested (struct FriendInfo *friend) * @param value Value to be compare * @return Closest peer */ -static struct GNUNET_PeerIdentity +static struct GNUNET_PeerIdentity select_closest_finger (const struct GNUNET_PeerIdentity *peer1, const struct GNUNET_PeerIdentity *peer2, uint64_t value) @@ -1590,7 +1723,6 @@ select_closest_finger (const struct GNUNET_PeerIdentity *peer1, peer1_value = GNUNET_ntohll (peer1_value); peer2_value = GNUNET_ntohll (peer2_value); - // TODO: Can use a simpler (to understand) idea here! if (peer1_value == value) { return *peer1; @@ -1601,31 +1733,30 @@ select_closest_finger (const struct GNUNET_PeerIdentity *peer1, 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; + } + else if (value < peer2_value && peer2_value < peer1_value) + { + 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; } - - //if (peer1_value < peer2_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; - //} - // } } @@ -1636,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. */ -static struct GNUNET_PeerIdentity +static struct GNUNET_PeerIdentity select_closest_predecessor (const struct GNUNET_PeerIdentity *peer1, const struct GNUNET_PeerIdentity *peer2, uint64_t value) @@ -1649,42 +1780,45 @@ select_closest_predecessor (const struct GNUNET_PeerIdentity *peer1, peer1_value = GNUNET_ntohll (peer1_value); peer2_value = GNUNET_ntohll (peer2_value); - if (peer1_value == value) + if (peer1_value == value) + { return *peer1; + } if (peer2_value == value) + { 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 (peer2_value < peer1_value) - //{ - 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; - //} - // } } #if 0 /** - * + * * */ void @@ -1693,7 +1827,7 @@ test_print_trail (struct GNUNET_PeerIdentity *trail, { struct GNUNET_PeerIdentity print_peer; int i; - + FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail_length = %d"), __FILE__, __func__,__LINE__,trail_length); for (i =0 ; i< trail_length; i++) @@ -1791,7 +1925,7 @@ test_finger_table_print() * @param is_predecessor Is value a predecessor or any other finger. * @return Closest peer among two peers. */ -static struct GNUNET_PeerIdentity +static struct GNUNET_PeerIdentity select_closest_peer (const struct GNUNET_PeerIdentity *peer1, const struct GNUNET_PeerIdentity *peer2, uint64_t value, @@ -1816,7 +1950,7 @@ select_closest_peer (const struct GNUNET_PeerIdentity *peer1, * Note: We use length as parameter. But we can use any other suitable parameter * also. * @param finger Finger Finger whose trail we have to select. - * @return Trail Selected Trail. + * @return Trail Selected Trail. */ static struct Trail * select_finger_trail (struct FingerInfo *finger) @@ -1844,7 +1978,7 @@ select_finger_trail (struct FingerInfo *finger) if (GNUNET_YES == is_friend_congested (friend)) continue; - if (NULL == best_trail || + if (NULL == best_trail || best_trail->trail_length > current_finger_trail->trail_length) { best_trail = current_finger_trail; @@ -1887,7 +2021,7 @@ compare_finger_and_current_closest_peer (struct Closest_Peer *current_closest_pe if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity, &my_identity)) continue; - + /* If finger is a friend, we have already checked it in previous function. */ if (NULL != (GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger->finger_identity))) @@ -1974,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) { @@ -1985,7 +2119,7 @@ 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. + current_closest_peer.finger_table_index = 65; //65 is a for non valid finger table index. return current_closest_peer; } @@ -1993,12 +2127,12 @@ init_current_successor (struct GNUNET_PeerIdentity my_identity, /** * Find locally best known peer, among your own identity, friend and finger list, * which is closest to given destination_finger_value. - * + * * 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 destination. * @param is_predecessor Are we looking for predecessor or finger? - * @return Closest_Peer that contains all the relevant field to reach to + * @return Closest_Peer that contains all the relevant field to reach to * @a destination_finger_value */ static struct Closest_Peer @@ -2008,9 +2142,9 @@ find_local_best_known_next_hop (uint64_t destination_finger_value, 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. */ @@ -2026,9 +2160,8 @@ find_local_best_known_next_hop (uint64_t destination_finger_value, return current_closest_peer; } + /** - * FIXME; Send put message across all the trail to reach to next hop to handle - * malicious peers. * Construct a Put message and send it to target_peer. * @param key Key for the content * @param block_type Type of the block @@ -2048,11 +2181,11 @@ find_local_best_known_next_hop (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, + 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, @@ -2064,7 +2197,7 @@ GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key, struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *pp; size_t msize; - + msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + sizeof (struct PeerPutMessage); if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) @@ -2073,14 +2206,13 @@ GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key, msize = data_size + sizeof (struct PeerPutMessage); } - /* Should it be GNUNET_SERVER_MAX_MESSAGE_SIZE? */ if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { DEBUG("msize = %lu\n",msize); GNUNET_break (0); return; } - + GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); @@ -2114,7 +2246,7 @@ GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key, /** - * Handle the put request from the client. + * Handle the put request from the client. * @param key Key for the content * @param block_type Type of the block * @param options Routing options @@ -2136,62 +2268,68 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key, 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, + 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; - DEBUG("PUT_REQUEST_RECEVIED KEY = %s \n",GNUNET_h2s(key)); 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. + 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 0 +#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, hop_count, put_path_length, put_path, + best_known_dest, + next_hop_finger->trail_list[i].trail_id, + &next_hop, 0, 1, &my_identity, expiration_time, data, data_size); } } + return; } - else #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); + 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); } /** - * FIXME; Send get message across all the trail to reach to next hop to handle - * malicious peers. * Construct a Get message and send it to target_peer. * @param key Key for the content * @param block_type Type of the block @@ -2236,7 +2374,7 @@ GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key, } GNUNET_assert (NULL != (target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); + GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer))); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); @@ -2261,15 +2399,15 @@ GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key, /** - * Handle the get request from the client file. If I am destination do + * 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. + * 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 +void GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type block_type, enum GNUNET_DHT_RouteOption options, @@ -2279,17 +2417,16 @@ GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key, 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, + successor = find_local_best_known_next_hop (key_value, GDS_FINGER_TYPE_NON_PREDECESSOR); - + best_known_dest = successor.best_known_destination; intermediate_trail_id = successor.trail_id; - - DEBUG("GET_REQUEST_RECEVIED KEY = %s \n",GNUNET_h2s(key)); + /* I am the destination. I have the data. */ if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &best_known_dest)) @@ -2298,10 +2435,39 @@ GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key, NULL, 0, 1, &my_identity, NULL,&my_identity); return; } - - /* fixme; for multiple trails, we need to send back finger index and send trail - across all the fingers. but in current implementation we don't have this case. - compare finger and current_successor returns, */ + +#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); @@ -2310,6 +2476,7 @@ GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key, /** * 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. @@ -2348,8 +2515,7 @@ GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key, if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { put_path_length = 0; - msize = msize - put_path_length; - return; + msize = msize - put_path_length * sizeof (struct GNUNET_PeerIdentity); } if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) @@ -2391,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]; @@ -2441,7 +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. */ @@ -2508,19 +2674,17 @@ compute_finger_identity_value (unsigned int finger_index) * 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_HashCode trail_id; struct GNUNET_HashCode intermediate_trail_id; unsigned int is_predecessor = 0; uint64_t finger_id_value; - - /* Schedule another send_find_finger_trail_message task. After one round of + + /* 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 + @@ -2545,7 +2709,7 @@ 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; - + /* 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)); @@ -2569,9 +2733,9 @@ 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 finger Finger + * @param finger Finger * @param new_finger_trail List of peers to reach from me to @a finger, NOT - * including the endpoints. + * 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. */ @@ -2609,9 +2773,9 @@ select_and_replace_trail (struct FingerInfo *finger, { 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); + next_hop); return; } @@ -2619,10 +2783,10 @@ select_and_replace_trail (struct FingerInfo *finger, 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, - *next_hop); - + next_hop); + /* Free the trail. */ while (NULL != (trail_element = replace_trail->trail_head)) { @@ -2635,7 +2799,7 @@ select_and_replace_trail (struct FingerInfo *finger, replace_trail->is_present = GNUNET_YES; replace_trail->trail_length = new_trail_length; replace_trail->trail_id = new_trail_id; - + for (i = 0; i < new_trail_length; i++) { struct Trail_Element *element = GNUNET_new (struct Trail_Element); @@ -2667,7 +2831,7 @@ is_new_trail_unique (struct FingerInfo *existing_finger, struct Trail_Element *trail_element; int i; int j; - + GNUNET_assert (existing_finger->trails_count > 0); /* Iterate over list of trails. */ @@ -2697,11 +2861,11 @@ is_new_trail_unique (struct FingerInfo *existing_finger, 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. + * 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 @@ -2717,11 +2881,11 @@ add_new_trail (struct FingerInfo *existing_finger, 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) @@ -2730,10 +2894,10 @@ add_new_trail (struct FingerInfo *existing_finger, 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; @@ -2750,7 +2914,7 @@ add_new_trail (struct FingerInfo *existing_finger, 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++) { @@ -2762,7 +2926,7 @@ add_new_trail (struct FingerInfo *existing_finger, trail->trail_tail, element); } - + 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; @@ -2772,11 +2936,11 @@ add_new_trail (struct FingerInfo *existing_finger, #if 0 -/** +/** * 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. + * 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 @@ -2792,11 +2956,11 @@ add_new_trail (struct FingerInfo *existing_finger, struct FriendInfo *first_friend; int i; int index; - + if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail, new_trail_length)) return; - + index = existing_finger->trails_count; trail = &existing_finger->trail_list[index]; GNUNET_assert (GNUNET_NO == trail->is_present); @@ -2886,9 +3050,9 @@ send_trail_teardown (struct FingerInfo *finger, } 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); } @@ -2900,11 +3064,13 @@ static void send_all_finger_trails_teardown (struct FingerInfo *finger) { unsigned int i; + for (i = 0; i < finger->trails_count; i++) { struct Trail *trail; + trail = &finger->trail_list[i]; - if (GNUNET_YES == trail->is_present); + if (GNUNET_YES == trail->is_present) { send_trail_teardown (finger, trail); trail->is_present = GNUNET_NO; @@ -2981,13 +3147,13 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, struct FingerInfo *new_entry; struct FriendInfo *first_trail_hop; struct Trail *trail; - int i; - + unsigned int i; + new_entry = GNUNET_new (struct FingerInfo); new_entry->finger_identity = finger_identity; new_entry->finger_table_index = finger_table_index; 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)) @@ -2997,7 +3163,7 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, GNUNET_free (new_entry); return; } - + /* Finger is a friend. */ if (0 == finger_trail_length) { @@ -3023,9 +3189,9 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger_trail[0]))); new_entry->trails_count = 1; - first_trail_hop->trails_count++; + first_trail_hop->trails_count++; /* Copy the finger trail into trail. */ - trail = GNUNET_new (struct Trail); + trail = &new_entry->trail_list[0]; for(i = 0; i < finger_trail_length; i++) { struct Trail_Element *element = GNUNET_new (struct Trail_Element); @@ -3037,16 +3203,13 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, trail->trail_tail, element); } - + /* 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); - return; } @@ -3054,12 +3217,11 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, * 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) +send_verify_successor_message (void *cls) { struct FriendInfo *target_friend; struct GNUNET_HashCode trail_id; @@ -3069,24 +3231,77 @@ send_verify_successor_message (void *cls, unsigned int i = 0; struct FingerInfo *successor; - /* After one round of verify successor, we do back off. */ - send_verify_successor_task = - GNUNET_SCHEDULER_add_delayed (verify_successor_next_send_time, - &send_verify_successor_message, - NULL); successor = &finger_table[0]; - /* Among all the trails to reach to successor, select first one which is present.*/ - for (i = 0; i < successor->trails_count; i++) - { - 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; - + + /* This task will be scheduled when the result for Verify Successor is received. */ + send_verify_successor_task = NULL; + + /* 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) + { + /* 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); + + ctx->num_retries_scheduled++; + send_verify_successor_retry_task = + GNUNET_SCHEDULER_add_delayed (verify_successor_retry_time, + &send_verify_successor_message, + ctx); + } + else + { + /* This is a retry attempt for verify_successor for a previous context */ + struct VerifySuccessorContext *ctx; + + ctx = cls; + ctx->num_retries_scheduled++; + send_verify_successor_retry_task = + GNUNET_SCHEDULER_add_delayed (verify_successor_retry_time, + &send_verify_successor_message, + ctx); + } + + /* Among all the trails to reach to successor, select first one which is present.*/ + for (i = 0; i < successor->trails_count; i++) + { + 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. */ @@ -3094,8 +3309,10 @@ send_verify_successor_message (void *cls, 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", - GNUNET_i2s(&my_identity), GNUNET_h2s(&trail->trail_id), __LINE__); + 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; } @@ -3134,7 +3351,7 @@ send_verify_successor_message (void *cls, /** * FIXME: should this be a periodic task, incrementing the search finger index? * Update the current search finger index. - * @a finger_identity + * @a finger_identity * @a finger_table_index */ static void @@ -3155,9 +3372,9 @@ update_current_search_finger_index (unsigned int finger_table_index) current_search_finger_index = PREDECESSOR_FINGER_ID; if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &successor->finger_identity)) { - if (GNUNET_SCHEDULER_NO_TASK == send_verify_successor_task) + if (NULL == send_verify_successor_task) { - send_verify_successor_task = + send_verify_successor_task = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL); } } @@ -3243,7 +3460,7 @@ get_finger_table_index (uint64_t ultimate_destination_finger_value, /** * Remove finger and its associated data structures from finger table. - * @param existing_finger Finger to be removed which is in finger table. + * @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. */ @@ -3267,7 +3484,6 @@ remove_existing_finger (struct FingerInfo *existing_finger, finger, and free the finger. */ send_all_finger_trails_teardown (existing_finger); free_finger (existing_finger, finger_table_index); - return; } @@ -3322,14 +3538,19 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, successor = &finger_table[0]; if (GNUNET_NO == successor->is_present) { - GNUNET_break (0); + GNUNET_break (0); //ASSERTION FAILS HERE. FIXME return; } if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &successor->finger_identity)) { -// find_finger_trail_task_next_send_time = -// GNUNET_TIME_STD_BACKOFF(find_finger_trail_task_next_send_time); + 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; GNUNET_STATISTICS_update (GDS_stats, gettext_noop @@ -3338,7 +3559,7 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, 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, @@ -3348,13 +3569,14 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, return; } } - + 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) { + /* Shorten the trail if possible. */ add_new_finger (finger_identity, finger_trail, finger_trail_length, finger_trail_id, finger_table_index); @@ -3385,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); } } } @@ -3403,7 +3625,7 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, { return; } - + /* If there is space to store more trails. */ if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER) add_new_trail (existing_finger, finger_trail, @@ -3418,8 +3640,6 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, /** - * FIXME: Check for loop in the request. If you already are part of put path, - * then you need to reset the put path length. * Core handler for P2P put messages. * @param cls closure * @param peer sender of the request @@ -3433,9 +3653,12 @@ 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; @@ -3445,14 +3668,6 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, size_t payload_size; uint64_t key_value; -#if ENABLE_MALICIOUS - if(1 == act_malicious) - { - DEBUG("I am malicious,dropping put request. \n"); - return GNUNET_OK; - } -#endif - msize = ntohs (message->size); if (msize < sizeof (struct PeerPutMessage)) { @@ -3466,22 +3681,28 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, 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)); @@ -3513,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 */ @@ -3533,7 +3755,7 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } } - + /* Check if you are already a part of put path. */ unsigned int i; for (i = 0; i < putlen; i++) @@ -3544,10 +3766,11 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, 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] = my_identity; @@ -3555,49 +3778,28 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, } 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) - { - DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line", - GNUNET_i2s(&my_identity), GNUNET_h2s(&intermediate_trail_id), __LINE__); - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop ("# Next hop to forward the packet not found " - "trail setup request, packet dropped."), - 1, GNUNET_NO); - - GNUNET_break_op (0); - //FIXME: Adding put here,only to ensure that process does not hang. but - // should not be here. fix the logic. - GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time), - &(put->key),putlen, pp, ntohl (put->block_type), - payload_size, payload); - return GNUNET_OK; - } - else + next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id, + GDS_ROUTING_SRC_TO_DEST); + if (NULL != next_routing_hop) { - GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, - next_hop)); + 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_local_best_known_next_hop (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), hop_count, @@ -3611,19 +3813,57 @@ 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, - 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; } @@ -3647,21 +3887,17 @@ 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; -#if ENABLE_MALICIOUS - if(1 == act_malicious) - { - DEBUG("I am malicious,dropping get request. \n"); - return GNUNET_OK; - } -#endif - msize = ntohs (message->size); if (msize < sizeof (struct PeerGetMessage)) { @@ -3671,30 +3907,38 @@ 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]; - hop_count = get->hop_count; - hop_count++; - 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; } - + +#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); - + /* Check if you are already a part of get path. */ unsigned int i; for (i = 0; i < get_length; i++) @@ -3705,7 +3949,7 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, break; } } - + /* Add yourself in the get path. */ struct GNUNET_PeerIdentity gp[get_length + 1]; memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity)); @@ -3714,60 +3958,79 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, 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 (&best_known_dest, &my_identity))) + 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) { - DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line", - GNUNET_i2s(&my_identity), GNUNET_h2s(&intermediate_trail_id), __LINE__); - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop ("# Next hop to forward the packet not found " - "GET request, packet dropped."), - 1, GNUNET_NO); - GNUNET_break (0); - /* We are not able to proceed further*/ - GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0, - get_length, gp, &gp[get_length - 2], - &my_identity); - return GNUNET_OK; + next_hop = *next_routing_hop; + best_known_dest = current_best_known_dest; + intermediate_trail_id = received_intermediate_trail_id; } } - else - { - struct Closest_Peer successor; - successor = find_local_best_known_next_hop (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; - } - /* I am the final destination. */ if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &best_known_dest)) { 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], + 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, hop_count, + intermediate_trail_id, &next_hop, hop_count, get_length, gp); } return GNUNET_YES; @@ -3812,9 +4075,9 @@ 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; @@ -3824,7 +4087,7 @@ handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, gettext_noop ("# Bytes received from other peers"), msize, GNUNET_NO); - + put_path = (const struct GNUNET_PeerIdentity *) &get_result[1]; get_path = &put_path[putlen]; payload = (const void *) &get_path[getlen]; @@ -3833,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; @@ -3856,7 +4120,8 @@ handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, 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; } @@ -3896,7 +4161,7 @@ get_local_best_known_next_hop (uint64_t final_dest_finger_val, current_dest)) { 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, @@ -3908,7 +4173,7 @@ get_local_best_known_next_hop (uint64_t final_dest_finger_val, 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); /* next_hop NULL is a valid case. This intermediate trail id is set by @@ -3969,12 +4234,12 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, } 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; trail_id = trail_setup->trail_id; @@ -3983,7 +4248,7 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, source = trail_setup->source_peer; is_predecessor = ntohl (trail_setup->is_predecessor); intermediate_trail_id = trail_setup->intermediate_trail_id; - + /* Did the friend insert its ID in the trail list? */ if (trail_length > 0 && 0 != memcmp (&trail_peer_list[trail_length-1], peer, sizeof (struct GNUNET_PeerIdentity))) @@ -3991,20 +4256,20 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, 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)) - { + { trail_length = 0; } - + /* Check if you are present in the trail seen so far? */ for (i = 0; i < trail_length ; i++) { if(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail_peer_list[i],&my_identity)) { /* We will add ourself later in code, if NOT destination. */ - trail_length = i; + trail_length = i; break; } } @@ -4014,11 +4279,11 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, { if (trail_length > 0) target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail_peer_list[trail_length - 1]); else target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &source); if(NULL == target_friend) { @@ -4052,13 +4317,13 @@ handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer, final_dest_finger_val, trail_id); return GNUNET_OK; } - + if (trail_length > 0) - target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, + target_friend = + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &trail_peer_list[trail_length-1]); else - target_friend = + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &source); if (NULL == target_friend) { @@ -4150,12 +4415,12 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p } 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; finger_identity = trail_result->finger_identity; @@ -4199,7 +4464,7 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p GNUNET_break_op(0); return GNUNET_SYSERR; } - + //TODO; Refactor code here and above to check if sender peer is correct if (my_index == 0) { @@ -4215,17 +4480,17 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p { if(my_index == trail_length - 1) { - GNUNET_assert(0 == + GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, - peer)); + peer)); } else - GNUNET_assert(0 == + 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,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++) { @@ -4335,8 +4598,8 @@ 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. + * 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. @@ -4356,28 +4619,28 @@ check_for_duplicate_entries (const struct GNUNET_PeerIdentity *trail_1, 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 * + 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)) { @@ -4385,30 +4648,30 @@ check_for_duplicate_entries (const struct GNUNET_PeerIdentity *trail_1, 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 * + 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; } @@ -4435,69 +4698,68 @@ get_trail_src_to_curr_pred (struct GNUNET_PeerIdentity source_peer, struct FingerInfo *current_predecessor; int i; unsigned int j; + unsigned int len; current_predecessor = &finger_table[PREDECESSOR_FINGER_ID]; - + /* Check if trail_src_to_me contains current_predecessor. */ for (i = 0; i < trail_src_to_me_len; i++) { - if(0 != GNUNET_CRYPTO_cmp_peer_identity(&trail_src_to_me[i], - ¤t_predecessor->finger_identity)) - continue; - - + if (0 != GNUNET_CRYPTO_cmp_peer_identity(&trail_src_to_me[i], + ¤t_predecessor->finger_identity)) + continue; + + *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++) + for (j = 0; j < i; j++) trail_src_to_curr_pred[j] = trail_src_to_me[j]; return trail_src_to_curr_pred; } - + 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; - - /* Source is NOT part of trail. */ - 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]; - } - GNUNET_free_non_null(trail_me_to_curr_pred); - return trail_src_to_curr_pred; + 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; + + /* Source is NOT part of trail. */ + 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; 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; } - - unsigned int len; - trail_src_to_curr_pred = check_for_duplicate_entries (trail_src_to_me, + + 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); + &len); *trail_src_to_curr_pred_length = len; GNUNET_free_non_null(trail_me_to_curr_pred); return trail_src_to_curr_pred; @@ -4545,7 +4807,7 @@ update_predecessor (struct GNUNET_PeerIdentity finger, 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. */ GDS_ROUTING_add (trail_to_new_predecessor_id, my_identity, @@ -4600,7 +4862,7 @@ compare_and_update_predecessor (struct GNUNET_PeerIdentity finger, update_predecessor (finger, trail, trail_length); return; } - + if (0 == GNUNET_CRYPTO_cmp_peer_identity (¤t_predecessor->finger_identity, &finger)) { @@ -4648,7 +4910,7 @@ handle_dht_p2p_verify_successor(void *cls, struct GNUNET_PeerIdentity *trail_src_to_curr_pred; unsigned int trail_length; size_t msize; - + msize = ntohs (message->size); if (msize < sizeof (struct PeerVerifySuccessorMessage)) @@ -4666,51 +4928,29 @@ handle_dht_p2p_verify_successor(void *cls, GNUNET_break_op (0); 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); + next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST); if (NULL == next_hop) { - //SUPUs anyways you are passing the trail, just do the lookup - // and pass the message forward. - int my_index = search_my_index (trail, trail_length); - if(-1 == my_index) - { - DEBUG(" Peer %s not present in trail id %s, line =%d", - GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__); - GNUNET_break_op (0); - return GNUNET_OK; - } - if((my_index == trail_length + 1)) - { - DEBUG(" Peer %s present twice in trail id %s, line =%d", - GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__); - GNUNET_break_op (0); - return GNUNET_OK; - } - if(my_index == (trail_length - 1)) - { - *next_hop = successor; - } - else - *next_hop = trail[my_index + 1]; + return GNUNET_OK; } - + target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); - + if(NULL == target_friend) { GNUNET_break_op(0); @@ -4728,12 +4968,12 @@ handle_dht_p2p_verify_successor(void *cls, * it. */ compare_and_update_predecessor (source_peer, trail, trail_length); 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, &source_peer))) { - trail_src_to_curr_pred = + trail_src_to_curr_pred = get_trail_src_to_curr_pred (source_peer, trail, trail_length, @@ -4744,7 +4984,7 @@ handle_dht_p2p_verify_successor(void *cls, trail_src_to_curr_pred_len = trail_length; unsigned int i; - trail_src_to_curr_pred = + 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++) @@ -4752,7 +4992,7 @@ handle_dht_p2p_verify_successor(void *cls, trail_src_to_curr_pred[i] = trail[i]; } } - + GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer))); @@ -4789,7 +5029,6 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, struct GNUNET_PeerIdentity *trail_to_new_successor; /* Probable successor is a friend */ - /* SUPUS: Here should I worry about friend,*/ if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, &probable_successor)) { @@ -4797,7 +5036,7 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, *trail_to_new_successor_length = 0; return trail_to_new_successor; } - + /* Is there any friend of yours in this trail. */ if(trail_me_to_probable_successor_len > 1) { @@ -4811,12 +5050,12 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, trail_to_new_successor = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)* *trail_to_new_successor_length); - + 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; } } @@ -4825,6 +5064,22 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, 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; +}; + + +void +send_notify_new_successor (void *cls); + /** * Check if the peer which sent us verify successor result message is still ours @@ -4835,7 +5090,7 @@ check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor, * @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 + * @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. @@ -4862,8 +5117,30 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, /* If probable successor is same as current_successor, do nothing. */ if(0 == GNUNET_CRYPTO_cmp_peer_identity (&probable_successor, ¤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; - + } closest_peer = select_closest_peer (&probable_successor, ¤t_successor->finger_identity, successor_value, is_predecessor); @@ -4872,13 +5149,13 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, if (0 == GNUNET_CRYPTO_cmp_peer_identity (&closest_peer , ¤t_successor->finger_identity)) { - //FIXME: Is this a good place to return the stats. + //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); @@ -4886,9 +5163,25 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, 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) { @@ -4900,7 +5193,7 @@ 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; trail_me_to_probable_succ = check_trail_me_to_probable_succ (probable_successor, @@ -4932,16 +5225,60 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, 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); +} + /* * Core handle for p2p verify successor result messages. * @param cls closure @@ -4982,37 +5319,45 @@ handle_dht_p2p_verify_successor_result(void *cls, } 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; trail_direction = ntohl (vsrm->trail_direction); trail_id = vsrm->trail_id; probable_successor = vsrm->probable_successor; current_successor = vsrm->current_successor; - + /* I am the querying_peer. */ if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity))) { - /* As we completed one round of verify successor, we can do backoff. */ -// verify_successor_next_send_time = -// GNUNET_TIME_STD_BACKOFF(verify_successor_next_send_time); + /* 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 */ if(NULL == (next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction))) { - //FIXME: Urgent in what case this is possible? - DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line", - GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__); + /* 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; } @@ -5074,22 +5419,27 @@ handle_dht_p2p_notify_new_successor(void *cls, 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; - + /* I am the new_successor to source_peer. */ if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_successor)) { if(trail_length > 0) GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail[trail_length - 1], peer)); - else + 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; } @@ -5112,12 +5462,8 @@ handle_dht_p2p_notify_new_successor(void *cls, 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. */ - if (GNUNET_SYSERR == GDS_ROUTING_add (trail_id, *peer, next_hop)) - { - GNUNET_break(0); - return GNUNET_OK; - } + + GDS_ROUTING_add(trail_id, *peer, next_hop); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop); if (NULL == target_friend) @@ -5133,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 @@ -5176,7 +5613,7 @@ handle_dht_p2p_trail_setup_rejection (void *cls, 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); congestion_timeout = trail_rejection->congestion_time; @@ -5207,7 +5644,7 @@ handle_dht_p2p_trail_setup_rejection (void *cls, /* First remove yourself from the trail. */ 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 == trail_length) next_peer = source; @@ -5240,9 +5677,9 @@ handle_dht_p2p_trail_setup_rejection (void *cls, /*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 @@ -5251,7 +5688,7 @@ handle_dht_p2p_trail_setup_rejection (void *cls, } target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer); - + if (NULL == target_friend) { DEBUG ("\nLINE = %d ,No friend found.",__LINE__); @@ -5270,7 +5707,7 @@ handle_dht_p2p_trail_setup_rejection (void *cls, { /* Here I was already part of trail. So no need to add. */ target_friend = - GNUNET_CONTAINER_multipeermap_get (friend_peermap, + GNUNET_CONTAINER_multipeermap_get (friend_peermap, &successor.next_hop); if (NULL == target_friend) { @@ -5278,7 +5715,7 @@ handle_dht_p2p_trail_setup_rejection (void *cls, GNUNET_break(0); return GNUNET_OK; } - + GDS_NEIGHBOURS_send_trail_setup (source, ultimate_destination_finger_value, successor.best_known_destination, @@ -5320,7 +5757,7 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer 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; @@ -5340,8 +5777,10 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer 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", - GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__); + 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; } @@ -5357,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; @@ -5409,16 +5848,12 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, 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)) { @@ -5446,7 +5881,8 @@ 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))); @@ -5486,7 +5922,7 @@ remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend, 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 (¤t_trail->trail_head->peer, disconnected_friend)) @@ -5540,20 +5976,20 @@ remove_matching_fingers (const struct GNUNET_PeerIdentity *disconnected_peer) for (i = 0; i < MAX_FINGERS; i++) { current_finger = &finger_table[i]; - + /* 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, ¤t_finger->finger_identity)) { 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, ¤t_finger->finger_identity)) @@ -5587,7 +6023,7 @@ handle_core_disconnect (void *cls, 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; @@ -5598,21 +6034,21 @@ handle_core_disconnect (void *cls, DEBUG("\n friend already disconnected."); return; } - + remove_matching_fingers (peer); GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer)); 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)) { @@ -5620,20 +6056,20 @@ handle_core_disconnect (void *cls, 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); @@ -5665,7 +6101,7 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity) friend = GNUNET_new (struct FriendInfo); friend->id = *peer_identity; - + GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (friend_peermap, peer_identity, friend, @@ -5673,10 +6109,10 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity) /* 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 + * 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 (GNUNET_SCHEDULER_NO_TASK == find_finger_trail_task) + if (NULL == find_finger_trail_task) { find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL); } @@ -5727,54 +6163,68 @@ GDS_NEIGHBOURS_init (void) {&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? + //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 = + + 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. + * 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[i]); + free_trail(&finger_table[i].trail_list[j]); } } } @@ -5797,17 +6247,33 @@ GDS_NEIGHBOURS_done (void) 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; } }