Kademlia Class Reference

Kademlia overlay module. More...

#include <Kademlia.h>

Inheritance diagram for Kademlia:
BaseOverlay BaseRpc TopologyVis RpcListener

List of all members.

Public Member Functions

 Kademlia ()
 ~Kademlia ()
void initializeOverlay (int stage)
 Initializes derived-class-attributes.
void finishOverlay ()
 collects statistical data in derived class
void joinOverlay ()
 Join the overlay with a given nodeID in thisNode.key.
bool isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err)
 Query if a node is among the siblings for a given key.
int getMaxNumSiblings ()
 Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.
int getMaxNumRedundantNodes ()
 Query the maximum number of redundant next hop nodes that are returned by findNode().
void handleTimerEvent (cMessage *msg)
bool handleRpcCall (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invocation messages.

Protected Member Functions

NodeVectorfindNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg)
 Implements the find node call.
void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
void handleBucketRefreshTimerExpired ()
 handle a expired bucket refresh timer
OverlayKey distance (const OverlayKey &x, const OverlayKey &y, bool useAlternative=false) const
 This method should implement the distance between two keys.
void updateTooltip ()
 updates information shown in GUI
virtual void lookupFinished (bool isValid)
virtual void handleNodeGracefulLeaveNotification ()
 This method gets call **.gracefulLeaveDelay seconds before it is killed if this node is among the gracefulLeaveProbability nodes.

Protected Attributes

uint32_t k
uint32_t b
uint32_t s
uint32_t maxStaleCount
bool exhaustiveRefresh
bool pingNewSiblings
bool secureMaintenance
 if true, ping not authenticated nodes before adding them to a bucket
bool newMaintenance
bool enableReplacementCache
bool replacementCachePing
uint replacementCandidates
int siblingRefreshNodes
int bucketRefreshNodes
simtime_t minSiblingTableRefreshInterval
simtime_t minBucketRefreshInterval
simtime_t siblingPingInterval
cMessage * bucketRefreshTimer
cMessage * siblingPingTimer

Private Member Functions

void routingInit ()
void routingDeinit ()
int routingBucketIndex (const OverlayKey &key, bool firstOnLayer=false)
 Returns the index of the bucket the key would reside with respect to Kademlia parameters.
KademliaBucketroutingBucket (const OverlayKey &key, bool ensure)
 Returns a Bucket or NULL if the bucket has not yet allocated.
bool routingAdd (const NodeHandle &handle, bool isAlive, simtime_t rtt=MAXTIME, bool maintenanceLookup=false)
 Adds a node to the routing table.
bool routingTimeout (const OverlayKey &key, bool immediately=false)
 Removes a node after a number of timeouts or immediately if immediately is true (behaves like routingRemove).
void refillSiblingTable ()
void sendSiblingFindNodeCall (const TransportAddress &dest)
void setBucketUsage (const OverlayKey &key)
bool handleFailedNode (const TransportAddress &failed)
 Handles a failed node.

Private Attributes

uint32_t bucketRefreshCount
uint32_t siblingTableRefreshCount
uint32_t nodesReplaced
KeyDistanceComparator
< KeyXorMetric > * 
comparator
KademliaBucketsiblingTable
std::vector< KademliaBucket * > routingTable
int numBuckets

Friends

class KademliaLookupListener

Detailed Description

Kademlia overlay module.

Author:
Sebastian Mies, Ingmar Baumgart, Bernhard Heep

Definition at line 44 of file Kademlia.h.


Constructor & Destructor Documentation

Kademlia::Kademlia (  ) 

Definition at line 155 of file Kademlia.cc.

00156 {
00157     siblingTable = NULL;
00158     comparator = NULL;
00159     bucketRefreshTimer = NULL;
00160     siblingPingTimer = NULL;
00161 }

Kademlia::~Kademlia (  ) 

Definition at line 163 of file Kademlia.cc.

00164 {
00165     routingDeinit();
00166 
00167     delete siblingTable;
00168     delete comparator;
00169     cancelAndDelete(bucketRefreshTimer);
00170     cancelAndDelete(siblingPingTimer);
00171 }


Member Function Documentation

OverlayKey Kademlia::distance ( const OverlayKey x,
const OverlayKey y,
bool  useAlternative = false 
) const [protected, virtual]

This method should implement the distance between two keys.

It may be overloaded to implement a new metric. The default implementation uses the standard-metric d = abs(x-y).

Parameters:
x Left-hand-side Key
y Right-hand-side key
useAlternative use an alternative distance metric
Returns:
OverlayKey Distance between x and y

Reimplemented from BaseOverlay.

Definition at line 1119 of file Kademlia.cc.

01122 {
01123     if (!useAlternative) return x^y; // KeyXorMetric().distance(x, y);
01124     return KeyPrefixMetric().distance(x, y);
01125 }

NodeVector * Kademlia::findNode ( const OverlayKey key,
int  numRedundantNodes,
int  numSiblings,
BaseOverlayMessage *  msg 
) [protected, virtual]

Implements the find node call.

This method simply returns the closest nodes known in the corresponding routing topology. If the node is a sibling for this key (isSiblingFor(key) = true), this method returns all numSiblings siblings, with the closest neighbor to the key first.

Parameters:
key The lookup key.
numRedundantNodes Maximum number of next hop nodes to return.
numSiblings number of siblings to return
msg A pointer to the BaseRouteMessage or FindNodeCall message of this lookup.
Returns:
NodeVector with closest nodes.

Reimplemented from BaseOverlay.

Definition at line 762 of file Kademlia.cc.

00764 {
00765     if (numSiblings > getMaxNumSiblings()) {
00766         opp_error("(Kademlia::findNode()) numRedundantNodes or numSiblings "
00767                   "too big!");
00768     }
00769 
00770 #if 0
00771     if (numRedundantNodes < 2) {
00772         throw cRuntimeError("Kademlia::findNode(): For Kademlia "
00773                                 "redundantNodes must be at least 2 "
00774                                 "and lookupMerge should be true!");
00775     }
00776 #endif
00777 
00778     // create temporary comparator
00779     KeyDistanceComparator<KeyXorMetric>* comp =
00780         new KeyDistanceComparator<KeyXorMetric>( key );
00781 
00782     // select result set size
00783     bool err;
00784     int resultSize;
00785 
00786     if (numSiblings < 0) {
00787         // exhaustive iterative doesn't care about siblings
00788         resultSize = numRedundantNodes;
00789     } else {
00790         resultSize = isSiblingFor(thisNode, key, numSiblings, &err) ?
00791                 (numSiblings ? numSiblings : 1) : numRedundantNodes;
00792     }
00793     assert(numSiblings || numRedundantNodes);
00794 
00795     NodeVector* result = new NodeVector(resultSize, comp);
00796 
00797     if (siblingTable->isEmpty()) {
00798         result->add(thisNode);
00799         delete comp;
00800         return result;
00801     }
00802 
00803     // add items from buckets
00804     int index;
00805     int mainIndex = routingBucketIndex(key);
00806     int startIndex = routingBucketIndex(key, true);
00807     int endIndex = routingBucketIndex(siblingTable->back().getKey());
00808 
00809     // add nodes from best fitting bucket
00810     if (mainIndex != -1) {
00811         KademliaBucket* bucket = routingTable[mainIndex];
00812         if (bucket != NULL && bucket->size()) {
00813             for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) {
00814                 result->add(*i);
00815                 //EV << "Kademlia::findNode(): Adding "
00816                 //   << *i << " from bucket " << mainIndex << endl;
00817             }
00818         }
00819     }
00820 
00821     // add most fitting buckets
00822     if (startIndex >= endIndex || !result->isFull()) {
00823         for (index = startIndex; index >= endIndex; --index) {
00824             // add bucket to result vector
00825             if (index == mainIndex) continue;
00826             KademliaBucket* bucket = routingTable[index];
00827             if (bucket != NULL && bucket->size()) {
00828                 for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) {
00829                     result->add(*i);
00830                     //EV << "Kademlia::routingGetClosestNodes(): Adding "
00831                     //   << *i << " from bucket " << index << endl;
00832                 }
00833             }
00834         }
00835 
00836         // add nodes from sibling table
00837         for (KademliaBucket::iterator i = siblingTable->begin();
00838              i != siblingTable->end(); i++) {
00839             result->add(*i);
00840         }
00841         // add local node
00842         result->add(thisNode);
00843     }
00844 
00845     // add more distant buckets
00846     for (index = mainIndex + 1; !result->isFull() && index < numBuckets;
00847          ++index) {
00848         // add bucket to result vector
00849         KademliaBucket* bucket = routingTable[index];
00850         if (bucket != NULL && bucket->size()) {
00851             for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) {
00852                 result->add(*i);
00853                 //EV << "[Kademlia::routingGetClosestNodes()]\n"
00854                 //   << "    Adding " << *i << " from bucket " << index
00855                 //   << endl;
00856             }
00857         }
00858     }
00859 
00860     delete comp;
00861 
00862     return result;
00863 }

void Kademlia::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

Definition at line 173 of file Kademlia.cc.

00174 {
00175     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00176     if (time < GlobalStatistics::MIN_MEASURED) return;
00177 
00178     globalStatistics->addStdDev("Kademlia: Nodes replaced in buckets/s",
00179                                 nodesReplaced / time);
00180     globalStatistics->addStdDev("Kademlia: Bucket Refreshes/s",
00181                                 bucketRefreshCount / time);
00182     globalStatistics->addStdDev("Kademlia: Sibling Table Refreshes/s",
00183                                 siblingTableRefreshCount / time);
00184 }

int Kademlia::getMaxNumRedundantNodes (  )  [virtual]

Query the maximum number of redundant next hop nodes that are returned by findNode().

Returns:
int number of redundant nodes returned by findNode().

Reimplemented from BaseOverlay.

Definition at line 273 of file Kademlia.cc.

00274 {
00275     return k;
00276 }

int Kademlia::getMaxNumSiblings (  )  [virtual]

Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.

Returns:
int number of siblings.

Reimplemented from BaseOverlay.

Definition at line 268 of file Kademlia.cc.

Referenced by findNode(), isSiblingFor(), sendSiblingFindNodeCall(), and setBucketUsage().

00269 {
00270     return s;
00271 }

void Kademlia::handleBucketRefreshTimerExpired (  )  [protected]

handle a expired bucket refresh timer

Definition at line 1037 of file Kademlia.cc.

Referenced by handleTimerEvent().

01038 {
01039     // refresh buckets
01040     if (state != READY || (((simTime() - siblingTable->getLastUsage()) >
01041                             minSiblingTableRefreshInterval))) {
01042         if (exhaustiveRefresh) {
01043             //TODO config shit
01044             int baseRedundantNodes = iterativeLookupConfig.redundantNodes;
01045             iterativeLookupConfig.redundantNodes = siblingRefreshNodes;
01046             createLookup(EXHAUSTIVE_ITERATIVE_ROUTING)->lookup(
01047                  getThisNode().getKey(), siblingRefreshNodes,
01048                  hopCountMax, 0, new KademliaLookupListener(this));
01049             iterativeLookupConfig.redundantNodes = baseRedundantNodes;
01050         } else if (newMaintenance) {
01051             //for (KademliaBucket::iterator i = siblingTable->begin();
01052             //     i != siblingTable->end(); i++) {
01053 
01054             //    sendSiblingFindNodeCall(*i);
01055             //}
01056             if (siblingTable->size()) {
01057                 sendSiblingFindNodeCall(siblingTable->at(intuniform(0,siblingTable->size()-1)));
01058             }
01059             state = READY;
01060             setOverlayReady(true);
01061         } else {
01062             createLookup()->lookup(getThisNode().getKey(), s, hopCountMax, 0,
01063                                    new KademliaLookupListener(this));
01064         }
01065         siblingTable->setLastUsage(simTime());
01066         ++siblingTableRefreshCount;
01067     }
01068 
01069     if (state == READY) {
01070         if (siblingTable->size()) {
01071             // get bit index of most significant digit that differs
01072             // from our next sibling's key to prevent us from refreshing
01073             // buckets, which can't contain any nodes
01074             int32_t diff = OverlayKey::getLength() - b*(getThisNode().getKey().
01075                 sharedPrefixLength(siblingTable->front().getKey(), b) + 1);
01076             int bucketsRefreshedPerTask = 0;
01077             for (int32_t i = OverlayKey::getLength() - b; i >= diff; i -=b ) {
01078                 for (int32_t d=0; d < ((1 << b) - 1); d++) {
01079                     int32_t index = (i / b) * ((1 << b) - 1) + d;
01080                     if (index < 0) continue;
01081                     if ((routingTable[index] == NULL) ||
01082                         ((simTime() - routingTable[index]->getLastUsage()) >
01083                         minBucketRefreshInterval)) {
01084 
01085                         OverlayKey refreshKey =
01086                             getThisNode().getKey() ^ (OverlayKey(d+1) << i);
01087 
01088                         if (exhaustiveRefresh) {
01089                             //TODO config stuff
01090                             int baseRedundantNodes = iterativeLookupConfig.redundantNodes;
01091                             iterativeLookupConfig.redundantNodes = bucketRefreshNodes;
01092                             createLookup(EXHAUSTIVE_ITERATIVE_ROUTING)->lookup(
01093                                 refreshKey, bucketRefreshNodes, hopCountMax,
01094                                 0, new KademliaLookupListener(this));
01095                             iterativeLookupConfig.redundantNodes = baseRedundantNodes;
01096                         } else {
01097                             createLookup()->lookup(refreshKey, s, hopCountMax, 0,
01098                                              new KademliaLookupListener(this));
01099                         }
01100 
01101                         ++bucketsRefreshedPerTask;
01102                         ++bucketRefreshCount;
01103                         setBucketUsage(refreshKey);
01104                     }
01105                 }
01106             }
01107             RECORD_STATS(globalStatistics->recordOutVector(
01108                                    "Kademlia: Buckets Refreshed Per Task",
01109                                    bucketsRefreshedPerTask));
01110         }
01111         // schedule next bucket refresh process
01112         cancelEvent(bucketRefreshTimer);
01113         scheduleAt(simTime() + (std::min(minSiblingTableRefreshInterval,
01114                         minBucketRefreshInterval) / 10.0), bucketRefreshTimer);
01115     }
01116 }

bool Kademlia::handleFailedNode ( const TransportAddress failed  )  [private, virtual]

Handles a failed node.

This method is called whenever a node given by findNode() was unreachable. The default implementation does nothing at all.

Parameters:
failed the failed node
Returns:
true if lookup should retry here

Reimplemented from BaseOverlay.

Definition at line 720 of file Kademlia.cc.

00721 {
00722     assert(!failed.isUnspecified());
00723 
00724     KademliaBucket::iterator i;
00725     // check sibling table
00726     for (i = siblingTable->begin(); i != siblingTable->end(); ++i) {
00727         if (failed == *i) break;
00728     }
00729 
00730     if (i != siblingTable->end()) {
00731         // remove from sibling table
00732         NodeHandle oldSibling = *i;
00733         siblingTable->erase(i);
00734 
00735         // call update() for removed sibling
00736         deleteOverlayNeighborArrow(oldSibling);
00737         callUpdate(oldSibling, false);
00738 
00739         updateTooltip();
00740 
00741         // try to refill with new closest contact
00742         refillSiblingTable();
00743     } else {
00744         // check buckets
00745         uint32_t m;
00746         for (m = 0; m < routingTable.size(); ++m) {
00747             if (routingTable[m] != NULL) {
00748                 for (i = routingTable[m]->begin(); i != routingTable[m]->end();
00749                      ++i) {
00750                     if (failed == *i) {
00751                         // remove from routing table
00752                         routingTable[m]->erase(i);
00753                         return (siblingTable->size() != 0);
00754                     }
00755                 }
00756             }
00757         }
00758     }
00759     return (siblingTable->size() != 0);
00760 }

void Kademlia::handleNodeGracefulLeaveNotification (  )  [protected, virtual]

This method gets call **.gracefulLeaveDelay seconds before it is killed if this node is among the gracefulLeaveProbability nodes.

Reimplemented from BaseOverlay.

Definition at line 705 of file Kademlia.cc.

00706 {
00707     // send failed node call to all siblings
00708     FailedNodeCall* call = new FailedNodeCall();
00709     call->setFailedNode(getThisNode());
00710     call->setBitLength(FAILEDNODECALL_L(call));
00711     for (KademliaBucket::iterator i = siblingTable->begin();
00712          i != siblingTable->end(); i++) {
00713         countFailedNodeCall(call);
00714         sendUdpRpcCall(*i, call->dup());
00715     }
00716 
00717     delete call;
00718 }

bool Kademlia::handleRpcCall ( BaseCallMessage *  msg  )  [virtual]

Processes Remote-Procedure-Call invocation messages.


This method should be overloaded when the overlay provides RPC functionality.

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

Definition at line 886 of file Kademlia.cc.

00887 {
00888     bool maintenanceLookup = (msg->getStatType() == MAINTENANCE_STAT);
00889     RPC_SWITCH_START(msg)
00890     RPC_ON_CALL(Ping) {
00891         // add active node
00892         OverlayCtrlInfo* ctrlInfo =
00893             check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo());
00894         routingAdd(ctrlInfo->getSrcRoute(), true, MAXTIME, maintenanceLookup);
00895         break;
00896     }
00897     RPC_ON_CALL(FindNode)
00898     {
00899         // add active node
00900         OverlayCtrlInfo* ctrlInfo =
00901             check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo());
00902         routingAdd(ctrlInfo->getSrcRoute(), true, MAXTIME, maintenanceLookup);
00903         break;
00904     }
00905     RPC_SWITCH_END()
00906     return false;
00907 }

void Kademlia::handleRpcResponse ( BaseResponseMessage *  msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [protected, virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

Definition at line 910 of file Kademlia.cc.

00913 {
00914     bool maintenanceLookup = (msg->getStatType() == MAINTENANCE_STAT);
00915     OverlayCtrlInfo* ctrlInfo =
00916         dynamic_cast<OverlayCtrlInfo*>(msg->getControlInfo());
00917     NodeHandle srcRoute = (ctrlInfo ? ctrlInfo->getSrcRoute()
00918                                     : msg->getSrcNode());
00919 
00920     RPC_SWITCH_START(msg)
00921         RPC_ON_RESPONSE(Ping) {
00922             if (state == INIT) {
00923                 // schedule bucket refresh timer
00924                 cancelEvent(bucketRefreshTimer);
00925                 scheduleAt(simTime(), bucketRefreshTimer);
00926                 cancelEvent(siblingPingTimer);
00927                 scheduleAt(simTime() + siblingPingInterval, siblingPingTimer);
00928                 state = JOIN;
00929             }
00930         }
00931         RPC_ON_RESPONSE(FindNode)
00932         {
00933             if (state == INIT) {
00934                 state = JOIN;
00935 
00936                 // bootstrap node is trustworthy: add all nodes immediately
00937                 routingAdd(srcRoute, true, rtt, maintenanceLookup);
00938                 for (uint32_t i=0; i<_FindNodeResponse->getClosestNodesArraySize(); i++)
00939                     routingAdd(_FindNodeResponse->getClosestNodes(i), true,
00940                                MAXTIME-1, maintenanceLookup);
00941 
00942                 if (newMaintenance) {
00943                     createLookup()->lookup(getThisNode().getKey(), s, hopCountMax, 0,
00944                                        new KademliaLookupListener(this));
00945                 } else {
00946                     // schedule bucket refresh timer
00947                     cancelEvent(bucketRefreshTimer);
00948                     scheduleAt(simTime(), bucketRefreshTimer);
00949                     cancelEvent(siblingPingTimer);
00950                     scheduleAt(simTime() + siblingPingInterval, siblingPingTimer);
00951                 }
00952 
00953                 break;
00954             }
00955 
00956             // add active node
00957             if (defaultRoutingType == SEMI_RECURSIVE_ROUTING ||
00958                 defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00959                 defaultRoutingType == RECURSIVE_SOURCE_ROUTING) {
00960                 rtt = MAXTIME;
00961             }
00962             setBucketUsage(srcRoute.getKey());
00963 
00964             // add inactive nodes
00965             for (uint32_t i=0; i<_FindNodeResponse->getClosestNodesArraySize(); i++)
00966                 routingAdd(_FindNodeResponse->getClosestNodes(i), false,
00967                            MAXTIME, maintenanceLookup);
00968             break;
00969         }
00970     RPC_SWITCH_END()
00971 
00972     // add node that responded
00973     routingAdd(srcRoute, true, rtt, maintenanceLookup);
00974 }

void Kademlia::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId,
const OverlayKey destKey 
) [protected, virtual]

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

Definition at line 977 of file Kademlia.cc.

00981 {
00982     if (dest.isUnspecified()) return;
00983     try {
00984         RPC_SWITCH_START(msg)
00985         RPC_ON_CALL(Ping) {
00986             if (state == INIT) {
00987                 joinOverlay();
00988                 return;
00989             }
00990 
00991             const NodeHandle& handle = dynamic_cast<const NodeHandle&>(dest);
00992             routingTimeout(handle.getKey());
00993             break;
00994         }
00995         RPC_ON_CALL(FindNode) {
00996             if (state == INIT) {
00997                 joinOverlay();
00998                 return;
00999             }
01000 
01001             const NodeHandle& handle = dynamic_cast<const NodeHandle&>(dest);
01002             routingTimeout(handle.getKey());
01003             setBucketUsage(handle.getKey());
01004             break;
01005         }
01006         RPC_SWITCH_END()
01007     } catch (...) {
01008         EV << "[Kademlia:handleRpcTimout() @ " << thisNode.getAddress()
01009            << " (" << thisNode.getKey().toString(16) << ")]\n"
01010            << "    ERROR: RPC timeout without key ("
01011            << msg << " -> " << dest << ")" << endl;
01012         return;
01013     }
01014 }

void Kademlia::handleTimerEvent ( cMessage *  msg  )  [virtual]

Reimplemented from BaseRpc.

Definition at line 868 of file Kademlia.cc.

00869 {
00870     if (msg == bucketRefreshTimer) {
00871         handleBucketRefreshTimerExpired();
00872     } else if (msg == siblingPingTimer) {
00873         if (siblingPingInterval == 0) {
00874             return;
00875         }
00876 
00877         for (KademliaBucket::iterator i = siblingTable->begin();
00878              i != siblingTable->end(); i++) {
00879             pingNode(*i);
00880         }
00881         scheduleAt(simTime() + siblingPingInterval, msg);
00882     }
00883 }

void Kademlia::initializeOverlay ( int  stage  )  [virtual]

Initializes derived-class-attributes.


Initializes derived-class-attributes, called by BaseOverlay::initialize(). By default this method is called once. If more stages are needed one can overload numInitStages() and add more stages.

Parameters:
stage the init stage

Reimplemented from BaseOverlay.

Definition at line 94 of file Kademlia.cc.

00095 {
00096     if (stage != MIN_STAGE_OVERLAY)
00097         return;
00098 
00099     // Kademlia provides KBR services
00100     kbr = true;
00101 
00102     // setup kademlia parameters
00103     minSiblingTableRefreshInterval = par("minSiblingTableRefreshInterval");
00104     minBucketRefreshInterval = par("minBucketRefreshInterval");
00105     siblingPingInterval = par("siblingPingInterval");
00106     exhaustiveRefresh = par("exhaustiveRefresh");
00107     maxStaleCount = par("maxStaleCount");
00108     pingNewSiblings = par("pingNewSiblings");
00109     enableReplacementCache = par("enableReplacementCache");
00110     replacementCachePing = par("replacementCachePing");
00111     replacementCandidates = par("replacementCandidates");
00112     secureMaintenance = par("secureMaintenance");
00113     newMaintenance = par("newMaintenance");
00114 
00115     k = par("k");
00116     b = par("b");
00117     s = par("s");
00118 
00119     siblingRefreshNodes = par("siblingRefreshNodes");
00120 
00121     if (siblingRefreshNodes <= 0) {
00122         siblingRefreshNodes = 5 * s;
00123     }
00124 
00125     bucketRefreshNodes = par("bucketRefreshNodes");
00126 
00127     if (bucketRefreshNodes <= 0) {
00128         bucketRefreshNodes = iterativeLookupConfig.redundantNodes;
00129     }
00130 
00131     // calculate number of buckets: ( (2^b)-1 ) * ( keylength / b )
00132     numBuckets = ((1L << b) - 1L) * (OverlayKey::getLength() / b);
00133 
00134     // init routing and sibling table
00135     siblingTable = new KademliaBucket(s * 5, NULL);
00136 
00137     // initialize pointers
00138     routingTable.assign(numBuckets, (KademliaBucket*)NULL);
00139 
00140     WATCH_VECTOR(*siblingTable);
00141     WATCH_VECTOR(routingTable);
00142 
00143     // self-message
00144     bucketRefreshTimer = new cMessage("bucketRefreshTimer");
00145     siblingPingTimer = new cMessage("siblingPingTimer");
00146 
00147     // statistics
00148     bucketRefreshCount = 0;
00149     siblingTableRefreshCount = 0;
00150     nodesReplaced = 0;
00151 
00152     comparator = NULL;
00153 }

bool Kademlia::isSiblingFor ( const NodeHandle node,
const OverlayKey key,
int  numSiblings,
bool *  err 
) [virtual]

Query if a node is among the siblings for a given key.

Query if a node is among the siblings for a given key. This means, that the nodeId of this node is among the closest numSiblings nodes to the key and that by a local findNode() call all other siblings to this key can be retrieved.

Parameters:
node the NodeHandle
key destination key
numSiblings The nodes knows all numSiblings nodes close to this key
err return false if the range could not be determined
Returns:
bool true, if the node is responsible for the key.

Reimplemented from BaseOverlay.

Definition at line 629 of file Kademlia.cc.

Referenced by findNode().

00631 {
00632     if (key.isUnspecified())
00633         error("Kademlia::isSiblingFor(): key is unspecified!");
00634 
00635     if (state != READY) {
00636         EV << "[Kademlia::isSiblingFor()] @ "
00637            << thisNode.getAddress()
00638            << " (" << thisNode.getKey().toString(16) << ")]\n"
00639            << "    state != READY"
00640            << endl;
00641         *err = true;
00642         return false;
00643     }
00644 
00645     if (numSiblings > getMaxNumSiblings()) {
00646         opp_error("Kademlia::isSiblingFor(): numSiblings too big!");
00647     }
00648 
00649     // set default number of siblings to consider
00650     if (numSiblings == -1) {
00651         numSiblings = getMaxNumSiblings();
00652     }
00653 
00654     if (numSiblings == 0) {
00655         *err = false;
00656         return (node.getKey() == key);
00657     }
00658 
00659     if (siblingTable->size() < (uint)numSiblings) {
00660         *err = false;
00661         return true;
00662     }
00663 
00664     if (siblingTable->isFull() &&
00665         ((thisNode.getKey() ^ key) >
00666          (thisNode.getKey() ^ siblingTable->back().getKey()))) {
00667         EV << "[Kademlia::isSiblingFor()] @ "
00668            << thisNode.getAddress()
00669            << " (" << thisNode.getKey().toString(16) << ")]\n"
00670            << "    Not sure if I am sibling for " << key << " !\n"
00671            << "    (" << key << " is not closer to me than "
00672            << siblingTable->back().getKey() << ")"
00673            << endl;
00674         *err = true;
00675         return false;
00676     }
00677 
00678     KeyDistanceComparator<KeyXorMetric>* comp =
00679         new KeyDistanceComparator<KeyXorMetric>(key);
00680 
00681     // create result vector
00682     NodeVector* result = new NodeVector(numSiblings, comp);
00683 
00684     for (KademliaBucket::iterator i=siblingTable->begin();
00685          i != siblingTable->end(); i++) {
00686         result->add( *i);
00687     }
00688 
00689     // add local node
00690     result->add(thisNode);
00691 
00692     *err = false;
00693     delete comp;
00694 
00695     if (result->contains(node.getKey())) {
00696         delete result;
00697         return true;
00698     } else {
00699         delete result;
00700         assert(!(numSiblings == 1 && key == node.getKey()));
00701         return false;
00702     }
00703 }

void Kademlia::joinOverlay (  )  [virtual]

Join the overlay with a given nodeID in thisNode.key.

Join the overlay with a given nodeID in thisNode.key. This method may be called by an application to join the overlay with a specific nodeID. It is also called if the node's IP address changes.

Reimplemented from BaseOverlay.

Definition at line 197 of file Kademlia.cc.

Referenced by handleRpcTimeout(), and lookupFinished().

00198 {
00199     // remove current node handle from the bootstrap list
00200     if (!thisNode.getKey().isUnspecified()) {
00201         bootstrapList->removeBootstrapNode(thisNode);
00202     }
00203 
00204     // initialize routing
00205     routingDeinit();
00206     routingInit();
00207 
00208     TransportAddress handle = bootstrapList->getBootstrapNode();
00209 
00210     if (!handle.isUnspecified()) {
00211         if (secureMaintenance) {
00212             sendSiblingFindNodeCall(handle);
00213         } else {
00214             // ping the bootstrap node to start bootstrapping
00215             pingNode(handle);
00216         }
00217     } else {
00218         // we're the only node in the network
00219         state = READY;
00220         setOverlayReady(true);
00221 
00222         // schedule bucket refresh timer
00223         cancelEvent(bucketRefreshTimer);
00224         scheduleAt(simTime(), bucketRefreshTimer);
00225         cancelEvent(siblingPingTimer);
00226         scheduleAt(simTime() + siblingPingInterval, siblingPingTimer);
00227     }
00228 }

void Kademlia::lookupFinished ( bool  isValid  )  [protected, virtual]

Definition at line 1016 of file Kademlia.cc.

Referenced by KademliaLookupListener::lookupFinished().

01017 {
01018     if (state == JOIN) {
01019         cancelEvent(bucketRefreshTimer);
01020 
01021         if (siblingTable->size() == 0) {
01022             // initial lookup failed - get new bootstrap node
01023             joinOverlay();
01024             return;
01025         }
01026 
01027         scheduleAt(simTime(), bucketRefreshTimer);
01028 
01029         if (!newMaintenance) {
01030             state = READY;
01031             setOverlayReady(true);
01032         }
01033     }
01034 }

void Kademlia::refillSiblingTable (  )  [private]

Definition at line 574 of file Kademlia.cc.

Referenced by handleFailedNode(), and routingTimeout().

00575 {
00576     if (siblingTable->size() == 0 ||
00577         siblingTable->isFull())
00578         return;
00579 
00580     int index = routingBucketIndex(siblingTable->back().getKey()) - 1;
00581     assert(index > 0);
00582 
00583     while ((routingTable[index] == NULL ||
00584             routingTable[index]->empty()) &&
00585             index < (int)(OverlayKey::getLength() - 1)) {
00586         index++;
00587     }
00588     if (index < (int)OverlayKey::getLength() &&
00589             routingTable[index] != NULL && routingTable[index]->size()) {
00590 
00591         KademliaBucket sortedBucket(k, comparator);
00592         for (uint32_t i = 0; i < routingTable[index]->size(); ++i) {
00593             sortedBucket.add(routingTable[index]->at(i));
00594         }
00595 
00596         siblingTable->add(sortedBucket.front());
00597 
00598         // call update() for new sibling
00599         if (!secureMaintenance) {
00600             showOverlayNeighborArrow(sortedBucket.front(), false,
00601                                      "m=m,50,100,50,100;ls=green,1");
00602             callUpdate(sortedBucket.front(), true);
00603         }
00604 
00605         // remove node from bucket
00606         routingTable[index]->erase(routingTable[index]->
00607               findIterator(sortedBucket.front().getKey()));
00608         assert(siblingTable->isFull());
00609         BUCKET_CONSISTENCY(routingTimeout: end refillSiblingTable());
00610     }
00611 }

bool Kademlia::routingAdd ( const NodeHandle handle,
bool  isAlive,
simtime_t  rtt = MAXTIME,
bool  maintenanceLookup = false 
) [private]

Adds a node to the routing table.

Parameters:
handle handle to add
isAlive true, if it is known that the node is alive
rtt measured round-trip-time to node
maintenanceLookup true, if this node was learned from a maintenance lookup
Returns:
true, if the node was known or has been added

maintenanceLookup ||

Definition at line 313 of file Kademlia.cc.

Referenced by handleRpcCall(), handleRpcResponse(), and routingTimeout().

00315 {
00316     BUCKET_CONSISTENCY(routingAdd: start);
00317     // never add unspecified node handles
00318     if (handle.isUnspecified() || handle.getKey() == getThisNode().getKey() )
00319         return false;
00320 
00321     // bucket index
00322     KademliaBucket::iterator i;
00323     bool result = false;
00324     bool authenticated = (isAlive && (rtt != MAXTIME));
00325 
00326     // convert node handle
00327     KademliaBucketEntry kadHandle = handle;
00328     kadHandle.setRtt(rtt);
00329     kadHandle.setLastSeen(simTime());
00330 
00331     /* check if node is already a sibling -----------------------------------*/
00332     if ((i = siblingTable->findIterator(handle.getKey()))
00333          != siblingTable->end()) {
00334         // not alive? -> do not change routing information
00335         if (isAlive) {
00336             if (!secureMaintenance || authenticated) {
00337                 if (kadHandle.getRtt() == MAXTIME) {
00338                     kadHandle.setRtt(i->getRtt());
00339                 }
00340                 // refresh sibling
00341                 (*i) = kadHandle;
00342             } else {
00343                 if (maintenanceLookup) {
00344                     return false;
00345                 }
00346 
00347                 if ((i->getAddress() != handle.getAddress()) ||
00348                     (i->getPort() != handle.getPort())) {
00349                     // sibling could have changed transport address
00350                     // ping new address for authentication
00351                     pingNode(handle);
00352                     return false;
00353                 }
00354             }
00355         }
00356         BUCKET_CONSISTENCY(routingAdd: node is sibling);
00357         return true;
00358     }
00359 
00360     /* check if node is already in a bucket ---------------------------------*/
00361     KademliaBucket* bucket = routingBucket(handle.getKey(), false);
00362     if (bucket != NULL && (i = bucket->findIterator(handle.getKey() ) )
00363             != bucket->end() ) {
00364         // not alive? -> do not change routing information
00365         if (isAlive) {
00366             if (!secureMaintenance || authenticated) {
00367                 if (kadHandle.getRtt() == MAXTIME) {
00368                     kadHandle.setRtt(i->getRtt());
00369                 }
00370 
00371                 // remove old handle
00372                 bucket->erase(i);
00373                 // re-add to tail
00374                 bucket->push_back(kadHandle);
00375             } else {
00376                 if (maintenanceLookup) {
00377                     return false;
00378                 }
00379 
00380                 if ((i->getAddress() != handle.getAddress()) ||
00381                     (i->getPort() != handle.getPort())) {
00382                     // sibling could have changed transport address
00383                     // ping new address for authentication
00384                     pingNode(handle);
00385                     return false;
00386                 }
00387             }
00388         }
00389 
00390         BUCKET_CONSISTENCY(routingAdd: node is in bucket);
00391         return true;
00392     }
00393 
00394     /* check if node can be added to the sibling list -----------------------*/
00395     if (siblingTable->isAddable(handle) ) {
00396         if (secureMaintenance && !authenticated) {
00397             if (!maintenanceLookup || (isAlive && (rtt == MAXTIME))) {
00398                 // received a FindNodeCall or PingCall from a potential sibling
00399                 // or new nodes from a FindNodeResponse app lookup
00400                 pingNode(handle);
00401             } else if (newMaintenance) {
00402                 // new node from sibling table refresh
00403                 //sendSiblingFindNodeCall(handle);
00404                 pingNode(handle);
00405             }
00406             return false;
00407         }
00408 
00409         bool finished = false;
00410         int siblingPos = -1;
00411 
00412         // check if sibling list is full so a handle is preemted from the list
00413         if (siblingTable->isFull()) {
00414             // get handle thats about to be preempted
00415             KademliaBucketEntry oldHandle = siblingTable->back();
00416             assert(oldHandle.getKey() != kadHandle.getKey());
00417 
00418             // add handle to the sibling list
00419             siblingPos = siblingTable->add(kadHandle);
00420 
00421             // change, so that the preempted handle is added to a bucket
00422             kadHandle = oldHandle;
00423 
00424             // call update() for removed sibling
00425             if (!secureMaintenance) {
00426                 deleteOverlayNeighborArrow(oldHandle);
00427                 callUpdate(oldHandle, false);
00428             }
00429 
00430             // return always true, since the handle has been added
00431             result = true;
00432         } else {
00433             // simply add the handle and stop
00434             siblingPos = siblingTable->add(kadHandle);
00435 
00436             // don't need to add kadHandle also to regular buckets
00437             finished = true;
00438         }
00439         assert(siblingPos > -1);
00440 
00441         // ping new siblings
00442         if ((pingNewSiblings && !isAlive)) {
00443             pingNode(handle);
00444         }
00445 
00446         updateTooltip();
00447 
00448         // call update() for new sibling
00449         showOverlayNeighborArrow(handle, false,
00450                                  "m=m,50,100,50,100;ls=green,1");
00451         callUpdate(handle, true);
00452 
00453         if (finished) {
00454             BUCKET_CONSISTENCY(routingAdd: node is now sibling);
00455             return true;
00456         }
00457     }
00458 
00459     /* add node to the appropriate bucket, if not full ---------------------*/
00460     bucket = routingBucket(kadHandle.getKey(), true);
00461     if (!bucket->isFull()) {
00462 
00463         if (secureMaintenance && !authenticated) {
00464             if ((isAlive && (rtt == MAXTIME))) {
00465                 // received a FindNodeCall or PingCall from a potential new bucket entry
00466                 // or new nodes from a FindNodeReponse app lookup
00467                 // optimization: don't send a ping for nodes from FindNodeResponse for app lookups
00468                 pingNode(kadHandle);
00469             }
00470             return false;
00471         }
00472 
00473         EV << "[Kademlia::routingAdd()]\n"
00474            << "    Adding new node " << kadHandle
00475            << " to bucket " << routingBucketIndex(kadHandle.getKey())
00476            << endl;
00477 
00478         bucket->push_back(kadHandle);
00479         result = true;
00480     } else if (isAlive) {
00481         if (enableReplacementCache && (!secureMaintenance || authenticated)) {
00482             bucket->replacementCache.push_front(kadHandle);
00483             if (bucket->replacementCache.size() > replacementCandidates) {
00484                 bucket->replacementCache.pop_back();
00485             }
00486 
00487             if (replacementCachePing) {
00488                 KademliaBucket::iterator it = bucket->begin();
00489                 while (it != bucket->end() && (it->getPingSent() == true)) {
00490                     it++;
00491                 }
00492                 if (it != bucket->end()) {
00493                     pingNode(*it);
00494                     it->setPingSent(true);
00495                 }
00496             }
00497         }
00498     }
00499 
00500     BUCKET_CONSISTENCY(routingAdd: end);
00501     return result;
00502 }

KademliaBucket * Kademlia::routingBucket ( const OverlayKey key,
bool  ensure 
) [private]

Returns a Bucket or NULL if the bucket has not yet allocated.

If ensure is true, the bucket allocation is ensured.

Parameters:
key The key of the node
ensure If true, the bucket allocation is ensured
Returns:
Bucket* The Bucket

Definition at line 297 of file Kademlia.cc.

Referenced by routingAdd(), routingTimeout(), and setBucketUsage().

00298 {
00299     // get bucket index
00300     int num = routingBucketIndex(key);
00301     if (num < 0)
00302         return NULL;
00303 
00304     // get bucket and allocate if necessary
00305     KademliaBucket* bucket = routingTable[ num ];
00306     if (bucket == NULL && ensure)
00307         bucket = routingTable[ num ] = new KademliaBucket( k, comparator );
00308 
00309     // return bucket
00310     return bucket;
00311 }

int Kademlia::routingBucketIndex ( const OverlayKey key,
bool  firstOnLayer = false 
) [private]

Returns the index of the bucket the key would reside with respect to Kademlia parameters.

Parameters:
key The key of the node
firstOnLayer If true bucket with smallest index on same layer is returned
Returns:
int The index of the bucket

Definition at line 278 of file Kademlia.cc.

Referenced by findNode(), refillSiblingTable(), routingAdd(), and routingBucket().

00279 {
00280     // calculate XOR distance
00281     OverlayKey delta = key ^ getThisNode().getKey();
00282 
00283     // find first subinteger that is not zero...
00284     int i;
00285     for (i = key.getLength() - b; i >= 0 && delta.getBitRange(i, b) == 0;
00286          i -= b);
00287 
00288     if (i < 0)
00289         return -1;
00290 
00291     if (!firstOnLayer)
00292         return (i / b) * ((1 << b) - 1) + (delta.getBitRange(i, b) - 1);
00293     else
00294         return (i / b) * ((1 << b) - 1) + (pow(2, b) - 2);
00295 }

void Kademlia::routingDeinit (  )  [private]

Definition at line 248 of file Kademlia.cc.

Referenced by joinOverlay(), and ~Kademlia().

00249 {
00250     // delete buckets
00251     for (uint32_t i = 0; i < routingTable.size(); i++) {
00252         if (routingTable[i] != NULL) {
00253             delete routingTable[i];
00254             routingTable[i] = NULL;
00255         }
00256     }
00257 
00258     if (siblingTable != NULL) {
00259         siblingTable->clear();
00260     }
00261 
00262     if (comparator != NULL) {
00263         delete comparator;
00264         comparator = NULL;
00265     }
00266 }

void Kademlia::routingInit (  )  [private]

Definition at line 232 of file Kademlia.cc.

Referenced by joinOverlay().

00233 {
00234     // set join state
00235     state = INIT;
00236 
00237     setOverlayReady(false);
00238 
00239     // setup comparator
00240     comparator = new KeyDistanceComparator<KeyXorMetric>(thisNode.getKey());
00241 
00242     siblingTable->setComparator(comparator);
00243 
00244     updateTooltip();
00245     BUCKET_CONSISTENCY(routingInit: end);
00246 }

bool Kademlia::routingTimeout ( const OverlayKey key,
bool  immediately = false 
) [private]

Removes a node after a number of timeouts or immediately if immediately is true (behaves like routingRemove).

Parameters:
key Node's key to remove
immediately If true, the node is removed immediately
Returns:
true, if the node has been removed

Definition at line 504 of file Kademlia.cc.

Referenced by handleRpcTimeout(), and refillSiblingTable().

00505 {
00506     BUCKET_CONSISTENCY(routingTimeout: start);
00507     // key unspecified? yes -> ignore
00508     if (key.isUnspecified())
00509         return false;
00510 
00511     // bucket index
00512     KademliaBucket::iterator i;
00513 
00514     /* check if the node is one of the siblings -----------------------------*/
00515     if ((i = siblingTable->findIterator(key)) != siblingTable->end()) {
00516 
00517         i->incStaleCount();
00518         i->setPingSent(false);
00519 
00520         if (i->getStaleCount() > maxStaleCount || immediately) {
00521             // remove from sibling table
00522             NodeHandle oldSibling = *i;
00523             siblingTable->erase(i);
00524 
00525             // lost last sibling?
00526             if (siblingTable->size() == 0) {
00527                 join();
00528                 return true;
00529             }
00530 
00531             BUCKET_CONSISTENCY(routingTimeout: is sibling);
00532 
00533             // try to refill with new closest contact
00534             refillSiblingTable();
00535 
00536             // call update() for removed sibling
00537             deleteOverlayNeighborArrow(oldSibling);
00538             callUpdate(oldSibling, false);
00539 
00540             updateTooltip();
00541 
00542             return true;
00543         }
00544     }
00545 
00546     /* check if node is already in a bucket ---------------------------------*/
00547     KademliaBucket* bucket = routingBucket(key, false);
00548     if (bucket != NULL && (i = bucket->findIterator(key) ) != bucket->end() ) {
00549 
00550         i->incStaleCount();
00551         i->setPingSent(false);
00552 
00553         if (i->getStaleCount() > maxStaleCount || immediately) {
00554             // remove from routing table
00555             bucket->erase(i);
00556 
00557             if (enableReplacementCache) {
00558                 if (bucket->replacementCache.size()) {
00559                     routingAdd(bucket->replacementCache.front(), true,
00560                                bucket->replacementCache.front().getRtt());
00561                     bucket->replacementCache.pop_front();
00562                     nodesReplaced++;
00563                 }
00564             }
00565         }
00566 
00567         BUCKET_CONSISTENCY(routingTimeout: is in bucket);
00568         return true;
00569     }
00570     BUCKET_CONSISTENCY(routingTimeout: end);
00571     return false;
00572 }

void Kademlia::sendSiblingFindNodeCall ( const TransportAddress dest  )  [private]

Definition at line 186 of file Kademlia.cc.

Referenced by handleBucketRefreshTimerExpired(), and joinOverlay().

00187 {
00188     FindNodeCall* call = new FindNodeCall("FindNodeCall");
00189     call->setExhaustiveIterative(true);
00190     call->setLookupKey(thisNode.getKey());
00191     call->setNumRedundantNodes(siblingRefreshNodes);
00192     call->setNumSiblings(getMaxNumSiblings());
00193     call->setBitLength(FINDNODECALL_L(call));
00194     sendUdpRpcCall(dest, call);
00195 }

void Kademlia::setBucketUsage ( const OverlayKey key  )  [private]

Definition at line 613 of file Kademlia.cc.

Referenced by handleBucketRefreshTimerExpired(), handleRpcResponse(), and handleRpcTimeout().

00614 {
00615     KademliaBucket* bucket = routingBucket(key, true);
00616 
00617     if (bucket) {
00618         bucket->setLastUsage(simTime());
00619     }
00620 
00621     if (((siblingTable->size() + 1) < (uint32_t)getMaxNumSiblings())
00622         || ((siblingTable->at(getMaxNumSiblings() - 2).getKey() ^ thisNode.getKey())
00623                 >= (key ^ thisNode.getKey()))) {
00624         siblingTable->setLastUsage(simTime());
00625     }
00626 
00627 }

void Kademlia::updateTooltip (  )  [protected]

updates information shown in GUI

Definition at line 1127 of file Kademlia.cc.

Referenced by handleFailedNode(), routingAdd(), routingInit(), and routingTimeout().

01128 {
01129     if (ev.isGUI()) {
01130         std::stringstream ttString;
01131 
01132         // show our nodeId in a tooltip
01133         ttString << "This: " << thisNode << endl << "Siblings: "
01134                  << siblingTable->size();
01135 
01136         getParentModule()->getParentModule()->getDisplayString().
01137         setTagArg("tt", 0, ttString.str().c_str());
01138         getParentModule()->getDisplayString().
01139         setTagArg("tt", 0, ttString.str().c_str());
01140         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
01141     }
01142 }


Friends And Related Function Documentation

friend class KademliaLookupListener [friend]

Definition at line 127 of file Kademlia.h.

Referenced by handleBucketRefreshTimerExpired(), and handleRpcResponse().


Member Data Documentation

uint32_t Kademlia::b [protected]
uint32_t Kademlia::bucketRefreshCount [private]

Definition at line 131 of file Kademlia.h.

Referenced by finishOverlay(), handleBucketRefreshTimerExpired(), and initializeOverlay().

Definition at line 64 of file Kademlia.h.

Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().

cMessage* Kademlia::bucketRefreshTimer [protected]

Definition at line 60 of file Kademlia.h.

Referenced by initializeOverlay(), routingAdd(), and routingTimeout().

bool Kademlia::exhaustiveRefresh [protected]

Definition at line 55 of file Kademlia.h.

Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().

uint32_t Kademlia::k [protected]
uint32_t Kademlia::maxStaleCount [protected]

Definition at line 52 of file Kademlia.h.

Referenced by initializeOverlay(), and routingTimeout().

simtime_t Kademlia::minBucketRefreshInterval [protected]

Definition at line 67 of file Kademlia.h.

Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().

Definition at line 66 of file Kademlia.h.

Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().

bool Kademlia::newMaintenance [protected]
uint32_t Kademlia::nodesReplaced [private]

Definition at line 133 of file Kademlia.h.

Referenced by finishOverlay(), initializeOverlay(), and routingTimeout().

int Kademlia::numBuckets [private]

Definition at line 139 of file Kademlia.h.

Referenced by findNode(), and initializeOverlay().

bool Kademlia::pingNewSiblings [protected]

Definition at line 56 of file Kademlia.h.

Referenced by initializeOverlay(), and routingAdd().

Definition at line 61 of file Kademlia.h.

Referenced by initializeOverlay(), and routingAdd().

Definition at line 62 of file Kademlia.h.

Referenced by initializeOverlay(), and routingAdd().

std::vector<KademliaBucket*> Kademlia::routingTable [private]
uint32_t Kademlia::s [protected]
bool Kademlia::secureMaintenance [protected]

if true, ping not authenticated nodes before adding them to a bucket

Definition at line 57 of file Kademlia.h.

Referenced by initializeOverlay(), joinOverlay(), refillSiblingTable(), and routingAdd().

simtime_t Kademlia::siblingPingInterval [protected]

Definition at line 68 of file Kademlia.h.

Referenced by handleRpcResponse(), handleTimerEvent(), initializeOverlay(), and joinOverlay().

cMessage* Kademlia::siblingPingTimer [protected]

Definition at line 132 of file Kademlia.h.

Referenced by finishOverlay(), handleBucketRefreshTimerExpired(), and initializeOverlay().


The documentation for this class was generated from the following files:
Generated on Wed May 26 16:21:17 2010 for OverSim by  doxygen 1.6.3