Kademlia overlay module. More...
#include <Kademlia.h>
Public Member Functions | |
Kademlia () | |
~Kademlia () | |
void | initializeOverlay (int stage) |
void | finishOverlay () |
void | joinOverlay () |
bool | isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err) |
int | getMaxNumSiblings () |
int | getMaxNumRedundantNodes () |
void | handleTimerEvent (cMessage *msg) |
bool | handleRpcCall (BaseCallMessage *msg) |
void | handleUDPMessage (BaseOverlayMessage *msg) |
virtual void | proxCallback (const TransportAddress &node, int rpcId, cPolymorphic *contextPointer, Prox prox) |
Protected Member Functions | |
NodeVector * | findNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg) |
void | handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt) |
void | handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey) |
void | handleBucketRefreshTimerExpired () |
handle a expired bucket refresh timer | |
OverlayKey | distance (const OverlayKey &x, const OverlayKey &y, bool useAlternative=false) const |
void | updateTooltip () |
updates information shown in GUI | |
virtual void | lookupFinished (bool isValid) |
virtual void | handleNodeGracefulLeaveNotification () |
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 |
bool | activePing |
bool | proximityRouting |
bool | proximityNeighborSelection |
bool | altRecMode |
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. | |
KademliaBucket * | routingBucket (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 | recursiveRoutingHook (const TransportAddress &dest, BaseRouteMessage *msg) |
bool | handleFailedNode (const TransportAddress &failed) |
Private Attributes | |
uint32_t | bucketRefreshCount |
uint32_t | siblingTableRefreshCount |
uint32_t | nodesReplaced |
KeyDistanceComparator < KeyXorMetric > * | comparator |
KademliaBucket * | siblingTable |
std::vector< KademliaBucket * > | routingTable |
int | numBuckets |
Friends | |
class | KademliaLookupListener |
Kademlia overlay module.
This class implements the Kademlia protocol described in P. Maymounkov and D. Mazières, "Kademlia: A Peer-to-Peer Information System Based on the XOR Metric", Lecture Notes in Computer Science, Peer-to-Peer Systems: First International Workshop (IPTPS 2002). Revised Papers, 2002, 2429/2002, 53-65
The recursive routing mode (R/Kademlia) is described in B. Heep, "R/Kademlia: Recursive and Topology-aware Overlay Routing", Proceedings of the Australasian Telecommunication Networks and Applications Conference 2010 (ATNAC 2010), Auckland, New Zealand, 2010
The security extensions (S/Kademlia) are described in I. Baumgart and S. Mies, "S/Kademlia: A Practicable Approach Towards Secure Key-Based Routing", Proceedings of the 13th International Conference on Parallel and Distributed Systems (ICPADS '07), Hsinchu, Taiwan, 2007
Definition at line 61 of file Kademlia.h.
Kademlia::Kademlia | ( | ) |
Definition at line 161 of file Kademlia.cc.
{ siblingTable = NULL; comparator = NULL; bucketRefreshTimer = NULL; siblingPingTimer = NULL; }
Kademlia::~Kademlia | ( | ) |
Definition at line 169 of file Kademlia.cc.
{ routingDeinit(); delete siblingTable; delete comparator; cancelAndDelete(bucketRefreshTimer); cancelAndDelete(siblingPingTimer); }
OverlayKey Kademlia::distance | ( | const OverlayKey & | x, | |
const OverlayKey & | y, | |||
bool | useAlternative = false | |||
) | const [protected] |
Definition at line 1378 of file Kademlia.cc.
{ if (!useAlternative) return x^y; // KeyXorMetric().distance(x, y); return KeyPrefixMetric().distance(x, y); }
NodeVector * Kademlia::findNode | ( | const OverlayKey & | key, | |
int | numRedundantNodes, | |||
int | numSiblings, | |||
BaseOverlayMessage * | msg | |||
) | [protected] |
Definition at line 928 of file Kademlia.cc.
Referenced by recursiveRoutingHook().
{ if (numSiblings > getMaxNumSiblings()) { opp_error("(Kademlia::findNode()) numRedundantNodes or numSiblings " "too big!"); } #if 0 if (numRedundantNodes < 2) { throw cRuntimeError("Kademlia::findNode(): For Kademlia " "redundantNodes must be at least 2 " "and lookupMerge should be true!"); } #endif // create temporary comparator KeyDistanceComparator<KeyXorMetric>* comp = new KeyDistanceComparator<KeyXorMetric>( key ); // select result set size bool err; int resultSize; if (numSiblings < 0) { // exhaustive iterative doesn't care about siblings resultSize = numRedundantNodes; } else { resultSize = isSiblingFor(thisNode, key, numSiblings, &err) ? (numSiblings ? numSiblings : 1) : numRedundantNodes; } assert(numSiblings || numRedundantNodes); NodeVector* result = new NodeVector(resultSize, comp); if (siblingTable->isEmpty()) { result->add(thisNode); delete comp; return result; } // R/Kademlia: in recursive mode just speed up route messages //TODO iterative PR bool returnProxNodes = false; if (proximityRouting) { if (msg && (!dynamic_cast<FindNodeCall*>(msg->getEncapsulatedPacket()) && !dynamic_cast<FindNodeCall*>(msg))) { returnProxNodes = true; } } ProxNodeVector* resultProx = NULL; KademliaPRComparator* compProx = NULL; if (returnProxNodes) { compProx = new KademliaPRComparator(key); resultProx = new ProxNodeVector(resultSize, NULL, NULL, compProx, 0, resultSize); } // add items from buckets int index; int mainIndex = routingBucketIndex(key); int startIndex = routingBucketIndex(key, true); int endIndex = routingBucketIndex(siblingTable->back().getKey()); // add nodes from best fitting bucket if (mainIndex != -1) { KademliaBucket* bucket = routingTable[mainIndex]; if (bucket != NULL && bucket->size()) { for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) { result->add(*i); if (returnProxNodes) resultProx->add(*i); //EV << "Kademlia::findNode(): Adding " // << *i << " from bucket " << mainIndex << endl; } } } // add most fitting buckets if (startIndex >= endIndex || !result->isFull()) { for (index = startIndex; index >= endIndex; --index) { // add bucket to result vector if (index == mainIndex) continue; KademliaBucket* bucket = routingTable[index]; if (bucket != NULL && bucket->size()) { for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) { result->add(*i); if (returnProxNodes) resultProx->add(*i);//std::make_pair(*i, i->getRtt())); //EV << "Kademlia::routingGetClosestNodes(): Adding " // << *i << " from bucket " << index << endl; } } } // add nodes from sibling table for (KademliaBucket::iterator i = siblingTable->begin(); i != siblingTable->end(); i++) { result->add(*i); if (returnProxNodes) resultProx->add(*i); } // add local node result->add(thisNode); if (returnProxNodes) { KademliaBucketEntry temp = thisNode; if (!result->size() || (*result)[0] == thisNode) { temp.setProx(Prox::PROX_SELF); resultProx->add(temp); } else { temp.setProx(Prox::PROX_UNKNOWN); resultProx->add(temp); } } } // add more distant buckets for (index = mainIndex + 1; !result->isFull() && index < numBuckets; ++index) { // add bucket to result vector KademliaBucket* bucket = routingTable[index]; if (bucket != NULL && bucket->size()) { for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) { result->add(*i); if (returnProxNodes) resultProx->add(*i); //EV << "[Kademlia::routingGetClosestNodes()]\n" // << " Adding " << *i << " from bucket " << index // << endl; } } } if (returnProxNodes) { result->clear(); for (uint32_t i = 0; i < resultProx->size(); ++i) { result->push_back((*resultProx)[i]/*.first*/); } delete compProx; delete resultProx; } delete comp; return result; }
void Kademlia::finishOverlay | ( | ) |
Definition at line 179 of file Kademlia.cc.
{ simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); if (time < GlobalStatistics::MIN_MEASURED) return; globalStatistics->addStdDev("Kademlia: Nodes replaced in buckets/s", nodesReplaced / time); globalStatistics->addStdDev("Kademlia: Bucket Refreshes/s", bucketRefreshCount / time); globalStatistics->addStdDev("Kademlia: Sibling Table Refreshes/s", siblingTableRefreshCount / time); }
int Kademlia::getMaxNumRedundantNodes | ( | ) |
Definition at line 279 of file Kademlia.cc.
{ return k; }
int Kademlia::getMaxNumSiblings | ( | ) |
Definition at line 274 of file Kademlia.cc.
Referenced by findNode(), isSiblingFor(), sendSiblingFindNodeCall(), and setBucketUsage().
{ return s; }
void Kademlia::handleBucketRefreshTimerExpired | ( | ) | [protected] |
handle a expired bucket refresh timer
Definition at line 1280 of file Kademlia.cc.
Referenced by handleTimerEvent().
{ // refresh buckets if (state != READY || (((simTime() - siblingTable->getLastUsage()) > minSiblingTableRefreshInterval))) { // R/Kademlia if (defaultRoutingType == SEMI_RECURSIVE_ROUTING || defaultRoutingType == FULL_RECURSIVE_ROUTING || defaultRoutingType == RECURSIVE_SOURCE_ROUTING) { //TODO real exhaustive-recursive lookup createLookup()->lookup(getThisNode().getKey() + OverlayKey::ONE, 0, hopCountMax, 0, new KademliaLookupListener(this)); } else if (exhaustiveRefresh) { //TODO config shit int baseRedundantNodes = iterativeLookupConfig.redundantNodes; iterativeLookupConfig.redundantNodes = siblingRefreshNodes; createLookup(EXHAUSTIVE_ITERATIVE_ROUTING)->lookup( getThisNode().getKey(), siblingRefreshNodes, hopCountMax, 0, new KademliaLookupListener(this)); iterativeLookupConfig.redundantNodes = baseRedundantNodes; } else if (newMaintenance) { //for (KademliaBucket::iterator i = siblingTable->begin(); // i != siblingTable->end(); i++) { // sendSiblingFindNodeCall(*i); //} if (siblingTable->size()) { sendSiblingFindNodeCall(siblingTable->at(intuniform(0,siblingTable->size()-1))); } state = READY; setOverlayReady(true); } else { createLookup()->lookup(getThisNode().getKey(), s, hopCountMax, 0, new KademliaLookupListener(this)); } siblingTable->setLastUsage(simTime()); ++siblingTableRefreshCount; } if (state == READY) { if (siblingTable->size()) { // get bit index of most significant digit that differs // from our next sibling's key to prevent us from refreshing // buckets, which can't contain any nodes int32_t diff = OverlayKey::getLength() - b*(getThisNode().getKey(). sharedPrefixLength(siblingTable->front().getKey(), b) + 1); int bucketsRefreshedPerTask = 0; for (int32_t i = OverlayKey::getLength() - b; i >= diff; i -=b ) { for (int32_t d=0; d < ((1 << b) - 1); d++) { int32_t index = (i / b) * ((1 << b) - 1) + d; if (index < 0) continue; if ((routingTable[index] == NULL) || ((simTime() - routingTable[index]->getLastUsage()) > minBucketRefreshInterval)) { OverlayKey refreshKey = getThisNode().getKey() ^ (OverlayKey(d+1) << i); // R/Kademlia if (defaultRoutingType == SEMI_RECURSIVE_ROUTING || defaultRoutingType == FULL_RECURSIVE_ROUTING || defaultRoutingType == RECURSIVE_SOURCE_ROUTING) { //TODO real exhaustive-recursive lookup createLookup()->lookup(refreshKey, 0, hopCountMax, 0, new KademliaLookupListener(this)); } else if (exhaustiveRefresh) { //TODO config shit int baseRedundantNodes = iterativeLookupConfig.redundantNodes; iterativeLookupConfig.redundantNodes = bucketRefreshNodes; createLookup(EXHAUSTIVE_ITERATIVE_ROUTING)->lookup( refreshKey, bucketRefreshNodes, hopCountMax, 0, new KademliaLookupListener(this)); iterativeLookupConfig.redundantNodes = baseRedundantNodes; } else { createLookup()->lookup(refreshKey, s, hopCountMax, 0, new KademliaLookupListener(this)); } ++bucketsRefreshedPerTask; ++bucketRefreshCount; setBucketUsage(refreshKey); } } } RECORD_STATS(globalStatistics->recordOutVector( "Kademlia: Buckets Refreshed Per Task", bucketsRefreshedPerTask)); } // schedule next bucket refresh process cancelEvent(bucketRefreshTimer); scheduleAt(simTime() + (std::min(minSiblingTableRefreshInterval, minBucketRefreshInterval) / 10.0), bucketRefreshTimer); } }
bool Kademlia::handleFailedNode | ( | const TransportAddress & | failed | ) | [private] |
Definition at line 805 of file Kademlia.cc.
{ assert(!failed.isUnspecified()); KademliaBucket::iterator i; // check sibling table for (i = siblingTable->begin(); i != siblingTable->end(); ++i) { if (failed == *i) break; } if (i != siblingTable->end()) { // remove from sibling table NodeHandle oldSibling = *i; siblingTable->erase(i); // call update() for removed sibling deleteOverlayNeighborArrow(oldSibling); callUpdate(oldSibling, false); updateTooltip(); // try to refill with new closest contact refillSiblingTable(); } else { // check buckets uint32_t m; for (m = 0; m < routingTable.size(); ++m) { if (routingTable[m] != NULL) { for (i = routingTable[m]->begin(); i != routingTable[m]->end(); ++i) { if (failed == *i) { // remove from routing table routingTable[m]->erase(i); return (siblingTable->size() != 0); } } } } } return (siblingTable->size() != 0); }
void Kademlia::handleNodeGracefulLeaveNotification | ( | ) | [protected, virtual] |
Definition at line 790 of file Kademlia.cc.
{ // send failed node call to all siblings FailedNodeCall* call = new FailedNodeCall(); call->setFailedNode(getThisNode()); call->setBitLength(FAILEDNODECALL_L(call)); for (KademliaBucket::iterator i = siblingTable->begin(); i != siblingTable->end(); i++) { countFailedNodeCall(call); sendUdpRpcCall(*i, call->dup()); } delete call; }
bool Kademlia::handleRpcCall | ( | BaseCallMessage * | msg | ) |
Definition at line 1116 of file Kademlia.cc.
{ bool maintenanceLookup = (msg->getStatType() == MAINTENANCE_STAT); RPC_SWITCH_START(msg) RPC_ON_CALL(Ping) { // add active node OverlayCtrlInfo* ctrlInfo = check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo()); routingAdd(ctrlInfo->getSrcRoute(), true, MAXTIME, maintenanceLookup); break; } RPC_ON_CALL(FindNode) { // add active node OverlayCtrlInfo* ctrlInfo = check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo()); routingAdd(ctrlInfo->getSrcRoute(), true, MAXTIME, maintenanceLookup); break; } RPC_SWITCH_END() return false; }
void Kademlia::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [protected] |
Definition at line 1140 of file Kademlia.cc.
{ bool maintenanceLookup = (msg->getStatType() == MAINTENANCE_STAT); OverlayCtrlInfo* ctrlInfo = dynamic_cast<OverlayCtrlInfo*>(msg->getControlInfo()); NodeHandle srcRoute = (ctrlInfo ? ctrlInfo->getSrcRoute() : msg->getSrcNode()); RPC_SWITCH_START(msg) RPC_ON_RESPONSE(Ping) { if (state == INIT) { // schedule bucket refresh timer cancelEvent(bucketRefreshTimer); scheduleAt(simTime(), bucketRefreshTimer); cancelEvent(siblingPingTimer); scheduleAt(simTime() + siblingPingInterval, siblingPingTimer); state = JOIN; } } RPC_ON_RESPONSE(FindNode) { if (state == INIT) { state = JOIN; // bootstrap node is trustworthy: add all nodes immediately routingAdd(srcRoute, true, rtt, maintenanceLookup); for (uint32_t i=0; i<_FindNodeResponse->getClosestNodesArraySize(); i++) routingAdd(_FindNodeResponse->getClosestNodes(i), true, MAXTIME-1, maintenanceLookup); if (newMaintenance) { createLookup()->lookup(getThisNode().getKey(), s, hopCountMax, 0, new KademliaLookupListener(this)); } else { // schedule bucket refresh timer cancelEvent(bucketRefreshTimer); scheduleAt(simTime(), bucketRefreshTimer); cancelEvent(siblingPingTimer); scheduleAt(simTime() + siblingPingInterval, siblingPingTimer); } break; } // add active node if (defaultRoutingType == SEMI_RECURSIVE_ROUTING || defaultRoutingType == FULL_RECURSIVE_ROUTING || defaultRoutingType == RECURSIVE_SOURCE_ROUTING) { rtt = MAXTIME; } setBucketUsage(srcRoute.getKey()); // add inactive nodes for (uint32_t i=0; i<_FindNodeResponse->getClosestNodesArraySize(); i++) routingAdd(_FindNodeResponse->getClosestNodes(i), false, MAXTIME, maintenanceLookup); break; } RPC_SWITCH_END() // add node that responded routingAdd(srcRoute, true, rtt, maintenanceLookup); }
void Kademlia::handleRpcTimeout | ( | BaseCallMessage * | msg, | |
const TransportAddress & | dest, | |||
cPolymorphic * | context, | |||
int | rpcId, | |||
const OverlayKey & | destKey | |||
) | [protected] |
Definition at line 1207 of file Kademlia.cc.
{ if (dest.isUnspecified()) return; try { RPC_SWITCH_START(msg) RPC_ON_CALL(Ping) { if (state == INIT) { joinOverlay(); return; } const NodeHandle& handle = dynamic_cast<const NodeHandle&>(dest); routingTimeout(handle.getKey()); break; } RPC_ON_CALL(FindNode) { if (state == INIT) { joinOverlay(); return; } const NodeHandle& handle = dynamic_cast<const NodeHandle&>(dest); routingTimeout(handle.getKey()); setBucketUsage(handle.getKey()); break; } RPC_SWITCH_END() } catch (...) { EV << "[Kademlia:handleRpcTimout() @ " << thisNode.getIp() << " (" << thisNode.getKey().toString(16) << ")]\n" << " ERROR: RPC timeout without key (" << msg << " -> " << dest << ")" << endl; return; } }
void Kademlia::handleTimerEvent | ( | cMessage * | msg | ) |
Definition at line 1078 of file Kademlia.cc.
{ if (msg == bucketRefreshTimer) { handleBucketRefreshTimerExpired(); } else if (msg == siblingPingTimer) { if (siblingPingInterval == 0) { return; } for (KademliaBucket::iterator i = siblingTable->begin(); i != siblingTable->end(); i++) { pingNode(*i); } scheduleAt(simTime() + siblingPingInterval, msg); } }
void Kademlia::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) |
Definition at line 1096 of file Kademlia.cc.
{ // only used for recursive Kademlia OverlayCtrlInfo* ctrlInfo = check_and_cast<OverlayCtrlInfo*>(msg->removeControlInfo()); KademliaRoutingInfoMessage* kadRoutingInfoMsg = check_and_cast<KademliaRoutingInfoMessage*>(msg); routingAdd(kadRoutingInfoMsg->getSrcNode(), true); for (uint32_t i = 0; i < kadRoutingInfoMsg->getNextHopsArraySize(); i++) { routingAdd(kadRoutingInfoMsg->getNextHops(i), kadRoutingInfoMsg->getNextHops(i).getIsAlive()); } delete ctrlInfo; delete msg; }
void Kademlia::initializeOverlay | ( | int | stage | ) |
Definition at line 94 of file Kademlia.cc.
{ if (stage != MIN_STAGE_OVERLAY) return; // Kademlia provides KBR services kbr = true; // setup kademlia parameters minSiblingTableRefreshInterval = par("minSiblingTableRefreshInterval"); minBucketRefreshInterval = par("minBucketRefreshInterval"); siblingPingInterval = par("siblingPingInterval"); exhaustiveRefresh = par("exhaustiveRefresh"); maxStaleCount = par("maxStaleCount"); pingNewSiblings = par("pingNewSiblings"); enableReplacementCache = par("enableReplacementCache"); replacementCachePing = par("replacementCachePing"); replacementCandidates = par("replacementCandidates"); secureMaintenance = par("secureMaintenance"); newMaintenance = par("newMaintenance"); // R/Kademlia activePing = par("activePing"); proximityRouting = par("proximityRouting"); proximityNeighborSelection = par("proximityNeighborSelection"); altRecMode = recordRoute = par("altRecMode"); k = par("k"); b = par("b"); s = par("s"); siblingRefreshNodes = par("siblingRefreshNodes"); if (siblingRefreshNodes <= 0) { siblingRefreshNodes = 5 * s; } bucketRefreshNodes = par("bucketRefreshNodes"); if (bucketRefreshNodes <= 0) { bucketRefreshNodes = iterativeLookupConfig.redundantNodes; } // calculate number of buckets: ( (2^b)-1 ) * ( keylength / b ) numBuckets = ((1L << b) - 1L) * (OverlayKey::getLength() / b); // init routing and sibling table siblingTable = new KademliaBucket(s * 5, NULL); // initialize pointers routingTable.assign(numBuckets, (KademliaBucket*)NULL); WATCH_VECTOR(*siblingTable); WATCH_VECTOR(routingTable); // self-message bucketRefreshTimer = new cMessage("bucketRefreshTimer"); siblingPingTimer = new cMessage("siblingPingTimer"); // statistics bucketRefreshCount = 0; siblingTableRefreshCount = 0; nodesReplaced = 0; comparator = NULL; }
bool Kademlia::isSiblingFor | ( | const NodeHandle & | node, | |
const OverlayKey & | key, | |||
int | numSiblings, | |||
bool * | err | |||
) |
Definition at line 714 of file Kademlia.cc.
Referenced by findNode().
{ if (key.isUnspecified()) error("Kademlia::isSiblingFor(): key is unspecified!"); if (state != READY) { EV << "[Kademlia::isSiblingFor()] @ " << thisNode.getIp() << " (" << thisNode.getKey().toString(16) << ")]\n" << " state != READY" << endl; *err = true; return false; } if (numSiblings > getMaxNumSiblings()) { opp_error("Kademlia::isSiblingFor(): numSiblings too big!"); } // set default number of siblings to consider if (numSiblings == -1) { numSiblings = getMaxNumSiblings(); } if (numSiblings == 0) { *err = false; return (node.getKey() == key); } if (siblingTable->size() < (uint)numSiblings) { *err = false; return true; } if (siblingTable->isFull() && ((thisNode.getKey() ^ key) > (thisNode.getKey() ^ siblingTable->back().getKey()))) { EV << "[Kademlia::isSiblingFor()] @ " << thisNode.getIp() << " (" << thisNode.getKey().toString(16) << ")]\n" << " Not sure if I am sibling for " << key << " !\n" << " (" << key << " is not closer to me than " << siblingTable->back().getKey() << ")" << endl; *err = true; return false; } KeyDistanceComparator<KeyXorMetric>* comp = new KeyDistanceComparator<KeyXorMetric>(key); // create result vector NodeVector* result = new NodeVector(numSiblings, comp); for (KademliaBucket::iterator i=siblingTable->begin(); i != siblingTable->end(); i++) { result->add( *i); } // add local node result->add(thisNode); *err = false; delete comp; if (result->contains(node.getKey())) { delete result; return true; } else { delete result; assert(!(numSiblings == 1 && key == node.getKey())); return false; } }
void Kademlia::joinOverlay | ( | ) |
Definition at line 203 of file Kademlia.cc.
Referenced by handleRpcTimeout(), and lookupFinished().
{ // remove current node handle from the bootstrap list if (!thisNode.getKey().isUnspecified()) { bootstrapList->removeBootstrapNode(thisNode); } // initialize routing routingDeinit(); routingInit(); TransportAddress handle = bootstrapList->getBootstrapNode(); if (!handle.isUnspecified()) { if (secureMaintenance) { sendSiblingFindNodeCall(handle); } else { // ping the bootstrap node to start bootstrapping pingNode(handle); } } else { // we're the only node in the network state = READY; setOverlayReady(true); // schedule bucket refresh timer cancelEvent(bucketRefreshTimer); scheduleAt(simTime(), bucketRefreshTimer); cancelEvent(siblingPingTimer); scheduleAt(simTime() + siblingPingInterval, siblingPingTimer); } }
void Kademlia::lookupFinished | ( | bool | isValid | ) | [protected, virtual] |
Definition at line 1259 of file Kademlia.cc.
Referenced by KademliaLookupListener::lookupFinished().
{ if (state == JOIN) { cancelEvent(bucketRefreshTimer); if (siblingTable->size() == 0) { // initial lookup failed - get new bootstrap node joinOverlay(); return; } scheduleAt(simTime(), bucketRefreshTimer); if (!newMaintenance) { state = READY; setOverlayReady(true); } } }
void Kademlia::proxCallback | ( | const TransportAddress & | node, | |
int | rpcId, | |||
cPolymorphic * | contextPointer, | |||
Prox | prox | |||
) | [virtual] |
Implements ProxListener.
Definition at line 1247 of file Kademlia.cc.
{ Enter_Method_Silent(); if (prox != Prox::PROX_TIMEOUT) { routingAdd((const NodeHandle&)node, true, prox.proximity); } else { routingTimeout(((const NodeHandle&)node).getKey()); } }
bool Kademlia::recursiveRoutingHook | ( | const TransportAddress & | dest, | |
BaseRouteMessage * | msg | |||
) | [private] |
Definition at line 848 of file Kademlia.cc.
{ if (msg->getSrcNode() != thisNode) { if (!msg->getDestKey().isUnspecified()) { routingAdd(msg->getSrcNode(), true); if (altRecMode && dest != thisNode) return true; NodeVector* nextHops = findNode(msg->getDestKey(), /*recursiveLookupConfig.redundantNodes*/ k, s, msg); KademliaRoutingInfoMessage* kadRoutingInfoMsg = new KademliaRoutingInfoMessage(); kadRoutingInfoMsg->setSrcNode(thisNode); kadRoutingInfoMsg->setDestKey(msg->getDestKey()); kadRoutingInfoMsg->setNextHopsArraySize(nextHops->size()); kadRoutingInfoMsg->setName("KadRoutingInfoMsg"); for (uint32_t i = 0; i < nextHops->size(); i++) { kadRoutingInfoMsg->setNextHops(i, (*nextHops)[i]); if (thisNode == kadRoutingInfoMsg->getNextHops(i)) { kadRoutingInfoMsg->getNextHops(i).setIsAlive(true); } } kadRoutingInfoMsg->setBitLength(KADEMLIAROUTINGINFO_L(kadRoutingInfoMsg)); delete nextHops; if (!altRecMode) { sendMessageToUDP(msg->getSrcNode(), kadRoutingInfoMsg); } else { // alternative maintenance mode std::vector<TransportAddress> sourceRoute; for (int i = msg->getVisitedHopsArraySize() - 1/*2*/; i >= 0; i--) { //TODO remove loops sourceRoute.push_back(msg->getVisitedHops(i)); } //sourceRoute.push_back(msg->getSrcNode()); sendToKey(OverlayKey::UNSPECIFIED_KEY, kadRoutingInfoMsg, 0, sourceRoute, NO_OVERLAY_ROUTING); } //TODO should be sent after baseroutemsg } else if (altRecMode && dynamic_cast<KademliaRoutingInfoMessage*>(msg-> getEncapsulatedPacket())) { // alternative mode: infoMsg on its way back KademliaRoutingInfoMessage* infoMsg = static_cast<KademliaRoutingInfoMessage*>(msg->decapsulate()); NodeVector* nextHops = findNode(infoMsg->getDestKey(), k, s, msg); // merge vectors KeyDistanceComparator<KeyXorMetric> comp(infoMsg->getDestKey()); MarkedNodeVector temp(UINT16_MAX, &comp); for (uint32_t i = 0; i < nextHops->size(); i++) { temp.push_back((*nextHops)[i]); } delete nextHops; for (uint32_t i = 0; i < infoMsg->getNextHopsArraySize(); i++) { routingAdd(infoMsg->getNextHops(i), infoMsg->getNextHops(i).getIsAlive()); temp.add(infoMsg->getNextHops(i)); } infoMsg->setNextHopsArraySize(temp.size()); for (uint32_t i = 0; i < temp.size(); ++i) { infoMsg->setNextHops(i, temp[i]); if (thisNode == infoMsg->getNextHops(i)) { infoMsg->getNextHops(i).setIsAlive(true); } } infoMsg->setBitLength(KADEMLIAROUTINGINFO_L(infoMsg)); msg->encapsulate(infoMsg); } } return true; }
void Kademlia::refillSiblingTable | ( | ) | [private] |
Definition at line 659 of file Kademlia.cc.
Referenced by handleFailedNode(), and routingTimeout().
{ if (siblingTable->size() == 0 || siblingTable->isFull()) return; int index = routingBucketIndex(siblingTable->back().getKey()) - 1; assert(index > 0); while ((routingTable[index] == NULL || routingTable[index]->empty()) && index < (int)(OverlayKey::getLength() - 1)) { index++; } if (index < (int)OverlayKey::getLength() && routingTable[index] != NULL && routingTable[index]->size()) { KademliaBucket sortedBucket(k, comparator); for (uint32_t i = 0; i < routingTable[index]->size(); ++i) { sortedBucket.add(routingTable[index]->at(i)); } siblingTable->add(sortedBucket.front()); // call update() for new sibling if (!secureMaintenance) { showOverlayNeighborArrow(sortedBucket.front(), false, "m=m,50,100,50,100;ls=green,1"); callUpdate(sortedBucket.front(), true); } // remove node from bucket routingTable[index]->erase(routingTable[index]-> findIterator(sortedBucket.front().getKey())); assert(siblingTable->isFull()); BUCKET_CONSISTENCY(routingTimeout: end refillSiblingTable()); } }
bool Kademlia::routingAdd | ( | const NodeHandle & | handle, | |
bool | isAlive, | |||
simtime_t | rtt = MAXTIME , |
|||
bool | maintenanceLookup = false | |||
) | [private] |
Adds a node to the routing table.
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 |
maintenanceLookup ||
Definition at line 319 of file Kademlia.cc.
Referenced by handleRpcCall(), handleRpcResponse(), handleUDPMessage(), proxCallback(), recursiveRoutingHook(), and routingTimeout().
{ BUCKET_CONSISTENCY(routingAdd: start); // never add unspecified node handles if (handle.isUnspecified() || handle.getKey() == getThisNode().getKey()) { return false; } // bucket index KademliaBucket::iterator i; bool result = false; bool authenticated = (isAlive && (rtt != MAXTIME)); bool needsRtt = (activePing && ((rtt == MAXTIME) ? true : false)); // convert node handle KademliaBucketEntry kadHandle = handle; kadHandle.setRtt(rtt); kadHandle.setLastSeen(simTime()); /* check if node is already a sibling -----------------------------------*/ if ((i = siblingTable->findIterator(handle.getKey())) != siblingTable->end()) { // not alive? -> do not change routing information if (isAlive) { if (!secureMaintenance || authenticated) { if (kadHandle.getRtt() == MAXTIME) { kadHandle.setRtt(i->getRtt()); } // refresh sibling (*i) = kadHandle; } else { if (maintenanceLookup) { return false; } if ((i->getIp() != handle.getIp()) || (i->getPort() != handle.getPort())) { // sibling could have changed transport address // ping new address for authentication pingNode(handle); return false; } } } BUCKET_CONSISTENCY(routingAdd: node is sibling); return true; } /* check if node is already in a bucket ---------------------------------*/ KademliaBucket* bucket = routingBucket(handle.getKey(), false); if (bucket != NULL && (i = bucket->findIterator(handle.getKey() ) ) != bucket->end() ) { // not alive? -> do not change routing information if (isAlive) { if (!secureMaintenance || authenticated) { if (kadHandle.getRtt() == MAXTIME) { kadHandle.setRtt(i->getRtt()); } // R/Kademlia if (needsRtt && (kadHandle.getRtt() == MAXTIME)) { Prox prox = neighborCache->getProx(handle, NEIGHBORCACHE_DEFAULT, -1, this, NULL); if (prox != Prox::PROX_SELF && prox != Prox::PROX_UNKNOWN && prox != Prox::PROX_TIMEOUT) { kadHandle.setProx(prox); //routingAdd(handle, true, prox.proximity);//ctrlInfo->getSrcRoute() //TODO } /*else if (prox == Prox::PROX_TIMEOUT) { // remove from bucket bucket->erase(i); return false; }*/ //TODO inform NC that node is alive else { return false; } } // remove old handle bucket->erase(i); // re-add to tail bucket->push_back(kadHandle); } else { if (maintenanceLookup) { return false; } if ((i->getIp() != handle.getIp()) || (i->getPort() != handle.getPort())) { // sibling could have changed transport address // ping new address for authentication pingNode(handle); return false; } } } BUCKET_CONSISTENCY(routingAdd: node is in bucket); return true; } /* check if node can be added to the sibling list -----------------------*/ if (siblingTable->isAddable(handle) ) { if (secureMaintenance && !authenticated) { if (!maintenanceLookup || (isAlive && (rtt == MAXTIME))) { // received a FindNodeCall or PingCall from a potential sibling // or new nodes from a FindNodeResponse app lookup pingNode(handle); } else if (newMaintenance) { // new node from sibling table refresh //sendSiblingFindNodeCall(handle); pingNode(handle); } return false; } // ping new siblings if (pingNewSiblings && !isAlive) { pingNode(handle); } // R/Kademlia else if (needsRtt) { // old version: pingNode(), now: Prox prox = neighborCache->getProx(handle, NEIGHBORCACHE_DEFAULT, -1, this, NULL); if (prox != Prox::PROX_SELF && prox != Prox::PROX_UNKNOWN && prox != Prox::PROX_TIMEOUT) { kadHandle.setProx(prox); } else if (prox == Prox::PROX_TIMEOUT) { // do not put handle into sibling table return false; } } bool finished = false; int siblingPos = -1; // check if sibling list is full so a handle is preemted from the list if (siblingTable->isFull()) { // get handle thats about to be preempted KademliaBucketEntry oldHandle = siblingTable->back(); assert(oldHandle.getKey() != kadHandle.getKey()); // add handle to the sibling list siblingPos = siblingTable->add(kadHandle); // change, so that the preempted handle is added to a bucket kadHandle = oldHandle; // call update() for removed sibling if (!secureMaintenance) { deleteOverlayNeighborArrow(oldHandle); callUpdate(oldHandle, false); } // return always true, since the handle has been added result = true; } else { // simply add the handle and stop siblingPos = siblingTable->add(kadHandle); // don't need to add kadHandle also to regular buckets finished = true; } assert(siblingPos > -1); updateTooltip(); // call update() for new sibling showOverlayNeighborArrow(handle, false, "m=m,50,100,50,100;ls=green,1"); callUpdate(handle, true); if (finished) { BUCKET_CONSISTENCY(routingAdd: node is now sibling); return true; } } /* add node to the appropriate bucket, if not full ---------------------*/ bucket = routingBucket(kadHandle.getKey(), true); if (!bucket->isFull()) { if (secureMaintenance && !authenticated) { if ((isAlive && (rtt == MAXTIME))) { // received a FindNodeCall or PingCall from a potential new bucket entry // or new nodes from a FindNodeReponse app lookup // optimization: don't send a ping for nodes from FindNodeResponse for app lookups pingNode(kadHandle); } return false; } EV << "[Kademlia::routingAdd()]\n" << " Adding new node " << kadHandle << " to bucket " << routingBucketIndex(kadHandle.getKey()) << endl; // PNS if (needsRtt || proximityNeighborSelection) { //pingNode(handle, -1, 0, NULL, NULL, NULL, -1, UDP_TRANSPORT, false); Prox prox = neighborCache->getProx(handle, NEIGHBORCACHE_DEFAULT, -1, this, NULL); if (prox != Prox::PROX_SELF && prox != Prox::PROX_UNKNOWN && prox != Prox::PROX_TIMEOUT) { //routingAdd(handle, true, prox.proximity);//ctrlInfo->getSrcRoute() //TODO kadHandle.setProx(prox); } } bucket->push_back(kadHandle); result = true; } else if (isAlive) { //PNS node replacement if (proximityNeighborSelection && kadHandle.getProx() != Prox::PROX_UNKNOWN) { KademliaBucket::iterator kickHim, it; kickHim = it = bucket->begin(); ++it; while (it != bucket->end()) { if (it->getRtt() > kickHim->getRtt()) { kickHim = it; } ++it; } if (kickHim->getRtt() > kadHandle.getRtt()) { KademliaBucketEntry temp = *kickHim; bucket->erase(kickHim); bucket->push_back(kadHandle); kadHandle = temp; } } if (enableReplacementCache && (!secureMaintenance || authenticated)) { bucket->replacementCache.push_front(kadHandle); if (bucket->replacementCache.size() > replacementCandidates) { bucket->replacementCache.pop_back(); } if (replacementCachePing) { KademliaBucket::iterator it = bucket->begin(); while (it != bucket->end() && (it->getPingSent() == true)) { it++; } if (it != bucket->end()) { pingNode(*it); it->setPingSent(true); } } } } // PNS else if (proximityNeighborSelection) { neighborCache->getProx(handle, NEIGHBORCACHE_QUERY, -1, this, NULL); //pingNode(handle); } BUCKET_CONSISTENCY(routingAdd: end); return result; }
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.
key | The key of the node | |
ensure | If true, the bucket allocation is ensured |
Definition at line 303 of file Kademlia.cc.
Referenced by routingAdd(), routingTimeout(), and setBucketUsage().
{ // get bucket index int num = routingBucketIndex(key); if (num < 0) return NULL; // get bucket and allocate if necessary KademliaBucket* bucket = routingTable[ num ]; if (bucket == NULL && ensure) bucket = routingTable[ num ] = new KademliaBucket( k, comparator ); // return bucket return bucket; }
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.
key | The key of the node | |
firstOnLayer | If true bucket with smallest index on same layer is returned |
Definition at line 284 of file Kademlia.cc.
Referenced by findNode(), refillSiblingTable(), routingAdd(), and routingBucket().
{ // calculate XOR distance OverlayKey delta = key ^ getThisNode().getKey(); // find first subinteger that is not zero... int i; for (i = key.getLength() - b; i >= 0 && delta.getBitRange(i, b) == 0; i -= b); if (i < 0) return -1; if (!firstOnLayer) return (i / b) * ((1 << b) - 1) + (delta.getBitRange(i, b) - 1); else return (i / b) * ((1 << b) - 1) + (pow(2, b) - 2); }
void Kademlia::routingDeinit | ( | ) | [private] |
Definition at line 254 of file Kademlia.cc.
Referenced by joinOverlay(), and ~Kademlia().
{ // delete buckets for (uint32_t i = 0; i < routingTable.size(); i++) { if (routingTable[i] != NULL) { delete routingTable[i]; routingTable[i] = NULL; } } if (siblingTable != NULL) { siblingTable->clear(); } if (comparator != NULL) { delete comparator; comparator = NULL; } }
void Kademlia::routingInit | ( | ) | [private] |
Definition at line 238 of file Kademlia.cc.
Referenced by joinOverlay().
{ // set join state state = INIT; setOverlayReady(false); // setup comparator comparator = new KeyDistanceComparator<KeyXorMetric>(thisNode.getKey()); siblingTable->setComparator(comparator); updateTooltip(); BUCKET_CONSISTENCY(routingInit: end); }
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).
key | Node's key to remove | |
immediately | If true, the node is removed immediately |
Definition at line 589 of file Kademlia.cc.
Referenced by handleRpcTimeout(), proxCallback(), and refillSiblingTable().
{ BUCKET_CONSISTENCY(routingTimeout: start); // key unspecified? yes -> ignore if (key.isUnspecified()) return false; // bucket index KademliaBucket::iterator i; /* check if the node is one of the siblings -----------------------------*/ if ((i = siblingTable->findIterator(key)) != siblingTable->end()) { i->incStaleCount(); i->setPingSent(false); if (i->getStaleCount() > maxStaleCount || immediately) { // remove from sibling table NodeHandle oldSibling = *i; siblingTable->erase(i); // lost last sibling? if (siblingTable->size() == 0) { join(); return true; } BUCKET_CONSISTENCY(routingTimeout: is sibling); // try to refill with new closest contact refillSiblingTable(); // call update() for removed sibling deleteOverlayNeighborArrow(oldSibling); callUpdate(oldSibling, false); updateTooltip(); return true; } } /* check if node is already in a bucket ---------------------------------*/ KademliaBucket* bucket = routingBucket(key, false); if (bucket != NULL && (i = bucket->findIterator(key) ) != bucket->end() ) { i->incStaleCount(); i->setPingSent(false); if (i->getStaleCount() > maxStaleCount || immediately) { // remove from routing table bucket->erase(i); if (enableReplacementCache) { if (bucket->replacementCache.size()) { routingAdd(bucket->replacementCache.front(), true, bucket->replacementCache.front().getRtt()); bucket->replacementCache.pop_front(); nodesReplaced++; } } } BUCKET_CONSISTENCY(routingTimeout: is in bucket); return true; } BUCKET_CONSISTENCY(routingTimeout: end); return false; }
void Kademlia::sendSiblingFindNodeCall | ( | const TransportAddress & | dest | ) | [private] |
Definition at line 192 of file Kademlia.cc.
Referenced by handleBucketRefreshTimerExpired(), and joinOverlay().
{ FindNodeCall* call = new FindNodeCall("FindNodeCall"); call->setExhaustiveIterative(true); call->setLookupKey(thisNode.getKey()); call->setNumRedundantNodes(siblingRefreshNodes); call->setNumSiblings(getMaxNumSiblings()); call->setBitLength(FINDNODECALL_L(call)); sendUdpRpcCall(dest, call); }
void Kademlia::setBucketUsage | ( | const OverlayKey & | key | ) | [private] |
Definition at line 698 of file Kademlia.cc.
Referenced by handleBucketRefreshTimerExpired(), handleRpcResponse(), and handleRpcTimeout().
{ KademliaBucket* bucket = routingBucket(key, true); if (bucket) { bucket->setLastUsage(simTime()); } if ((siblingTable->size() < (uint32_t)getMaxNumSiblings()) || ((siblingTable->at(getMaxNumSiblings() - 1).getKey() ^ thisNode.getKey()) >= (key ^ thisNode.getKey()))) { siblingTable->setLastUsage(simTime()); } }
void Kademlia::updateTooltip | ( | ) | [protected] |
updates information shown in GUI
Definition at line 1386 of file Kademlia.cc.
Referenced by handleFailedNode(), routingAdd(), routingInit(), and routingTimeout().
{ if (ev.isGUI()) { std::stringstream ttString; // show our nodeId in a tooltip ttString << "This: " << thisNode << endl << "Siblings: " << siblingTable->size(); getParentModule()->getParentModule()->getDisplayString(). setTagArg("tt", 0, ttString.str().c_str()); getParentModule()->getDisplayString(). setTagArg("tt", 0, ttString.str().c_str()); getDisplayString().setTagArg("tt", 0, ttString.str().c_str()); } }
friend class KademliaLookupListener [friend] |
Definition at line 155 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), and handleRpcResponse().
bool Kademlia::activePing [protected] |
Definition at line 84 of file Kademlia.h.
Referenced by initializeOverlay(), and routingAdd().
bool Kademlia::altRecMode [protected] |
Definition at line 87 of file Kademlia.h.
Referenced by initializeOverlay(), and recursiveRoutingHook().
uint32_t Kademlia::b [protected] |
Definition at line 66 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), initializeOverlay(), and routingBucketIndex().
uint32_t Kademlia::bucketRefreshCount [private] |
Definition at line 159 of file Kademlia.h.
Referenced by finishOverlay(), handleBucketRefreshTimerExpired(), and initializeOverlay().
int Kademlia::bucketRefreshNodes [protected] |
Definition at line 81 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().
cMessage* Kademlia::bucketRefreshTimer [protected] |
Definition at line 93 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), handleRpcResponse(), handleTimerEvent(), initializeOverlay(), joinOverlay(), Kademlia(), lookupFinished(), and ~Kademlia().
KeyDistanceComparator<KeyXorMetric>* Kademlia::comparator [private] |
Definition at line 163 of file Kademlia.h.
Referenced by initializeOverlay(), Kademlia(), refillSiblingTable(), routingBucket(), routingDeinit(), routingInit(), and ~Kademlia().
bool Kademlia::enableReplacementCache [protected] |
Definition at line 77 of file Kademlia.h.
Referenced by initializeOverlay(), routingAdd(), and routingTimeout().
bool Kademlia::exhaustiveRefresh [protected] |
Definition at line 72 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().
uint32_t Kademlia::k [protected] |
Definition at line 65 of file Kademlia.h.
Referenced by getMaxNumRedundantNodes(), initializeOverlay(), recursiveRoutingHook(), refillSiblingTable(), and routingBucket().
uint32_t Kademlia::maxStaleCount [protected] |
Definition at line 69 of file Kademlia.h.
Referenced by initializeOverlay(), and routingTimeout().
simtime_t Kademlia::minBucketRefreshInterval [protected] |
Definition at line 90 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().
simtime_t Kademlia::minSiblingTableRefreshInterval [protected] |
Definition at line 89 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), and initializeOverlay().
bool Kademlia::newMaintenance [protected] |
Definition at line 75 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), handleRpcResponse(), initializeOverlay(), lookupFinished(), and routingAdd().
uint32_t Kademlia::nodesReplaced [private] |
Definition at line 161 of file Kademlia.h.
Referenced by finishOverlay(), initializeOverlay(), and routingTimeout().
int Kademlia::numBuckets [private] |
Definition at line 167 of file Kademlia.h.
Referenced by findNode(), and initializeOverlay().
bool Kademlia::pingNewSiblings [protected] |
Definition at line 73 of file Kademlia.h.
Referenced by initializeOverlay(), and routingAdd().
bool Kademlia::proximityNeighborSelection [protected] |
Definition at line 86 of file Kademlia.h.
Referenced by initializeOverlay(), and routingAdd().
bool Kademlia::proximityRouting [protected] |
Definition at line 85 of file Kademlia.h.
Referenced by findNode(), and initializeOverlay().
bool Kademlia::replacementCachePing [protected] |
Definition at line 78 of file Kademlia.h.
Referenced by initializeOverlay(), and routingAdd().
uint Kademlia::replacementCandidates [protected] |
Definition at line 79 of file Kademlia.h.
Referenced by initializeOverlay(), and routingAdd().
std::vector<KademliaBucket*> Kademlia::routingTable [private] |
Definition at line 166 of file Kademlia.h.
Referenced by findNode(), handleBucketRefreshTimerExpired(), handleFailedNode(), initializeOverlay(), refillSiblingTable(), routingBucket(), and routingDeinit().
uint32_t Kademlia::s [protected] |
Definition at line 67 of file Kademlia.h.
Referenced by getMaxNumSiblings(), handleBucketRefreshTimerExpired(), handleRpcResponse(), initializeOverlay(), and recursiveRoutingHook().
bool Kademlia::secureMaintenance [protected] |
if true, ping not authenticated nodes before adding them to a bucket
Definition at line 74 of file Kademlia.h.
Referenced by initializeOverlay(), joinOverlay(), refillSiblingTable(), and routingAdd().
simtime_t Kademlia::siblingPingInterval [protected] |
Definition at line 91 of file Kademlia.h.
Referenced by handleRpcResponse(), handleTimerEvent(), initializeOverlay(), and joinOverlay().
cMessage* Kademlia::siblingPingTimer [protected] |
Definition at line 94 of file Kademlia.h.
Referenced by handleRpcResponse(), handleTimerEvent(), initializeOverlay(), joinOverlay(), Kademlia(), and ~Kademlia().
int Kademlia::siblingRefreshNodes [protected] |
Definition at line 80 of file Kademlia.h.
Referenced by handleBucketRefreshTimerExpired(), initializeOverlay(), and sendSiblingFindNodeCall().
KademliaBucket* Kademlia::siblingTable [private] |
Definition at line 165 of file Kademlia.h.
Referenced by findNode(), handleBucketRefreshTimerExpired(), handleFailedNode(), handleNodeGracefulLeaveNotification(), handleTimerEvent(), initializeOverlay(), isSiblingFor(), Kademlia(), lookupFinished(), refillSiblingTable(), routingAdd(), routingDeinit(), routingInit(), routingTimeout(), setBucketUsage(), updateTooltip(), and ~Kademlia().
uint32_t Kademlia::siblingTableRefreshCount [private] |
Definition at line 160 of file Kademlia.h.
Referenced by finishOverlay(), handleBucketRefreshTimerExpired(), and initializeOverlay().