#include <Broose.h>
Public Member Functions | |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | finishOverlay () |
collects statistical data in derived class | |
virtual bool | isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err) |
Query if a node is among the siblings for a given key. | |
virtual void | joinOverlay () |
Join the overlay with a given nodeID in thisNode.key. | |
virtual void | handleUDPMessage (BaseOverlayMessage *msg) |
Processes messages from underlay. | |
virtual void | recordOverlaySentStats (BaseOverlayMessage *msg) |
Collect overlay specific sent messages statistics. | |
virtual bool | handleRpc (BaseCallMessage *msg) |
Processes Remote-Procedure-Call invokation messages. | |
virtual void | handleTimerEvent (cMessage *msg) |
Processes "timer" self-messages. | |
void | updateTooltip () |
updates information shown in tk-environment | |
Protected Member Functions | |
void | handleJoinTimerExpired (cMessage *msg) |
handles a expired join timer | |
void | handleBucketTimerExpired (cMessage *msg) |
handles a expired bucket refresh timer | |
void | changeState (int state) |
changes the node's state | |
NodeVector * | findNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg) |
Implements the find node call. | |
bool | keyBelongsToNode (const OverlayKey &key) |
decides if a specific key is managed by this node | |
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 | displayBucketState () |
debug function which output the content of the node's buckets | |
void | binaryOutput (const OverlayKey &key) |
outputs an Overlay key in the binary system | |
void | handleRpcResponse (BaseResponseMessage *msg, int rpcId, simtime_t rtt) |
This method is called if an RPC response has been received. | |
void | handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcId, const OverlayKey &destKey) |
This method is called if an RPC timeout has been reached. | |
void | handleFindNodeTimeout (FindNodeCall *findNode, const TransportAddress &dest, const OverlayKey &destKey) |
This method is called if an Find Node Call timeout has been reached. | |
void | handleBucketRequestRpc (BucketCall *msg) |
handles a received Bucket request | |
void | handleBucketResponseRpc (BucketResponse *msg) |
handles a received Bucket response | |
void | handleBucketTimeout (BucketCall *msg) |
handles a received Bucket timeout | |
void | handleBroosePingRequestRpc (BroosePingCall *msg) |
handles a received Ping request | |
void | handleBroosePingResponseRpc (BroosePingResponse *msg, simtime_t rtt) |
handles a received Ping response | |
void | handleBroosePingTimeout (BroosePingCall *msg, const TransportAddress &dest, const OverlayKey &destKey) |
handles a received Ping timeout | |
void | setLastSeen (NodeHandle node) |
updates the timestamp of a node in all buckets | |
void | addNode (NodeHandle node, int bucket=0) |
adds a node to all buckets | |
void | resetFailedResponses (NodeHandle node) |
resets the counter of failed responses | |
void | setRTT (NodeHandle node, simtime_t rtt) |
sets the rtt to a node in all buckets | |
Protected Attributes | |
int | chooseLookup |
decides which kind of lookup (right/left shifting) is used | |
int | joinDelay |
time interval between two join tries | |
int | protoState |
the state in which a node currently is | |
int | receivedJoinResponse |
number of received join response messages | |
int | receivedBBucketLookup |
number of received lookup responses for the B bucket | |
int | numberBBucketLookup |
maximal number of lookup reponses for the B bucket | |
int | receivedLBucketLookup |
number of received lookup responses for the L bucket | |
int | numberLBucketLookup |
maximal number of lookup reponses for the L bucket | |
int | shiftingBits |
number of bits shifted in/out each step | |
int | powShiftingBits |
2^{variable shiftingBits} | |
uint | bucketSize |
maximal number of bucket entries | |
uint | rBucketSize |
maximal number of entries in the r buckets | |
int | parallelRequests |
number ob parallel requests | |
int | keyLength |
length of the node and data IDs | |
bool | refresh |
is the node restarting the bootstrap protocol or is it a new node | |
int | pingDelay |
time intervall between bucket refreshs | |
int | refreshTime |
time intervall after which a ping is done | |
uint | userDist |
how many hops are added to the estimated hop count | |
int | numPings |
actual number of received ping messages | |
int | maxPings |
total number of ping messages | |
int | numberRetries |
number of retries in case of timeout | |
int | bucketCount |
number of Bucket messages | |
int | bucketBytesSent |
length of all Bucket messages | |
int | broosePingCount |
number of Ping messages | |
int | broosePingBytesSent |
length of all Ping messages | |
int | numFailedPackets |
number of packets which couldn't be routed correctly | |
BrooseBucket * | lBucket |
BrooseBucket * | bBucket |
BrooseBucket ** | rBucket |
cMessage * | join_timer |
cMessage * | bucket_timer |
timer to reconstruct all buckets | |
NodeHandle | bootstrapNode |
node handle holding the bootstrap node | |
BrooseHandle | thisBrooseNode |
this is a BrooseHandle of the current node like thisNode | |
Friends | |
class | BrooseBucket |
void Broose::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.
stage | the init stage |
Reimplemented from BaseOverlay.
00033 { 00034 // because of IPAddressResolver, we need to wait until interfaces 00035 // are registered, address auto-assignment takes place etc. 00036 if(stage != MIN_STAGE_OVERLAY) 00037 return; 00038 00039 // fetch some parameters 00040 bucketSize = par("bucketSize"); // = k 00041 rBucketSize = par("rBucketSize"); // = k' 00042 parallelRequests = par("parallelRequests"); // not implemented yet 00043 joinDelay = par("joinDelay"); 00044 shiftingBits = par("shiftingBits"); 00045 pingDelay = par("pingDelay"); 00046 userDist = par("userDist"); 00047 refreshTime = par("refreshTime"); 00048 numberRetries = par("numberRetries"); 00049 00050 //statistics 00051 bucketCount = 0; 00052 bucketBytesSent = 0; 00053 broosePingCount = 0; 00054 broosePingBytesSent = 0; 00055 00056 //init local parameters 00057 chooseLookup = 0; 00058 receivedJoinResponse = 0; 00059 receivedBBucketLookup = 0; 00060 numberBBucketLookup = 0; 00061 receivedLBucketLookup = 0; 00062 numberLBucketLookup = 0; 00063 powShiftingBits = (int) pow(2.0, shiftingBits); 00064 keyLength = OverlayKey::getLength(); 00065 numFailedPackets = 0; 00066 refresh = false; 00067 numPings = 0; 00068 maxPings = 0; 00069 00070 // add some watches 00071 WATCH(receivedJoinResponse); 00072 WATCH(receivedBBucketLookup); 00073 WATCH(numberBBucketLookup); 00074 WATCH(receivedLBucketLookup); 00075 WATCH(numberLBucketLookup); 00076 WATCH(numPings); 00077 WATCH(maxPings); 00078 00079 // get module references - these are references to the buckets 00080 // each node have in order to get a lookup done 00081 rBucket = new BrooseBucket*[powShiftingBits]; 00082 00083 for (int i = 0; i < powShiftingBits; i++) { 00084 rBucket[i] = check_and_cast<BrooseBucket*> 00085 (parentModule()->submodule("rBucket",i)); 00086 } 00087 00088 lBucket = check_and_cast<BrooseBucket*> 00089 (parentModule()->submodule("lBucket")); 00090 00091 bBucket = check_and_cast<BrooseBucket*> 00092 (parentModule()->submodule("bBucket")); 00093 00094 // create join and bucket timer 00095 join_timer = new cMessage("join_timer"); 00096 bucket_timer = new cMessage("bucket_timer"); 00097 }
void Broose::finishOverlay | ( | ) | [virtual] |
collects statistical data in derived class
Reimplemented from BaseOverlay.
00539 { 00540 // print out statistics and delete pointers 00541 00542 // delete timer 00543 cancelEvent(join_timer); 00544 delete join_timer; 00545 00546 cancelEvent(bucket_timer); 00547 delete bucket_timer; 00548 00549 // remove this node from the bootstrap list 00550 removeBootstrapNode(thisNode); 00551 00552 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); 00553 if(time == 0) return; 00554 00555 globalStatistics->addStdDev("Number of non-routable packets/s", numFailedPackets / time); 00556 00557 globalStatistics->addStdDev("Broose: Sent BUCKET Messages/s", bucketCount / time); 00558 globalStatistics->addStdDev("Broose: Sent BUCKET Byte/s", bucketBytesSent / time); 00559 00560 globalStatistics->addStdDev("Broose: Sent BROOSEPING Messages/s", broosePingCount / time); 00561 globalStatistics->addStdDev("Broose: Sent BROOSEPING Bytes/s", broosePingBytesSent / time); 00562 }
bool Broose::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.
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 |
Reimplemented from BaseOverlay.
00610 { 00611 // TODO: node != thisNode doesn't work yet 00612 if (key.isUnspecified()) 00613 error("Broose::isSiblingFor(): key is unspecified!"); 00614 00615 if (node != thisNode) 00616 error("Broose::isSiblingsFor(): " 00617 "node != thisNode is not implemented!"); 00618 00619 if (numSiblings > getMaxNumSiblings()) { 00620 opp_error("Broose::isSiblingFor(): numSiblings too big!"); 00621 } 00622 // set default number of siblings to consider 00623 if (numSiblings == -1) numSiblings = getMaxNumSiblings(); 00624 00625 if (protoState != READY) { 00626 *err = true; 00627 return false; 00628 } 00629 00630 return bBucket->keyInRange(key); 00631 }
void Broose::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.
00100 { 00101 changeState(INIT); 00102 00103 // if the bootstrap node is unspecified we are the only node in the network 00104 // so we can skip the "normal" join protocol 00105 if (bootstrapNode.isUnspecified()) { 00106 changeState(READY); 00107 } 00108 }
void Broose::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
void Broose::recordOverlaySentStats | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Collect overlay specific sent messages statistics.
This method is called from BaseOverlay::sendMessageToUDP() for every overlay message that is sent by a node. Use this to collect statistical data for overlay protocol specific message types.
msg | The overlay message to be sent to the UDP layer |
Reimplemented from BaseOverlay.
00565 { 00566 BaseOverlayMessage* innerMsg; 00567 00568 if (msg->getType() == OVERLAYROUTE) 00569 innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg()); 00570 else 00571 innerMsg = msg; 00572 00573 switch (innerMsg->getType()) { 00574 00575 case RPC: { 00576 if ((dynamic_cast<BucketCall*>(innerMsg) != NULL) || 00577 (dynamic_cast<BucketResponse*>(innerMsg) != NULL)) { 00578 RECORD_STATS(bucketCount++; bucketBytesSent += 00579 msg->byteLength()); 00580 } else if ((dynamic_cast<BroosePingCall*>(innerMsg) != NULL) || 00581 (dynamic_cast<BroosePingResponse*>(innerMsg) != NULL)) { 00582 RECORD_STATS(broosePingCount++; broosePingBytesSent += 00583 msg->byteLength()); 00584 } 00585 break; 00586 } 00587 } 00588 }
bool Broose::handleRpc | ( | BaseCallMessage * | msg | ) | [virtual] |
Processes Remote-Procedure-Call invokation messages.
This method should be overloaded when the overlay provides RPC functionality.
Reimplemented from BaseRpc.
00667 { 00668 if (protoState == BSET || protoState == READY) { 00669 // delegate messages 00670 RPC_SWITCH_START( msg ) 00671 // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> ) 00672 RPC_DELEGATE(Bucket, handleBucketRequestRpc); 00673 RPC_DELEGATE(BroosePing, handleBroosePingRequestRpc); 00674 RPC_SWITCH_END( ) 00675 return RPC_HANDLED; 00676 } else { 00677 // EV << "[Broose::handleRpc() @ " << thisNode.ip 00678 // << " (" << thisNode.key.toString(16) << ")]\n" 00679 // << " Received RPC call and state != READY || BSET!" 00680 // << endl; 00681 return false; 00682 } 00683 }
void Broose::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Processes "timer" self-messages.
msg | A self-message |
Reimplemented from BaseOverlay.
00256 { 00257 if(msg->isName("join_timer")) 00258 handleJoinTimerExpired(msg); 00259 else if (msg->isName("bucket_timer")) 00260 handleBucketTimerExpired(msg); 00261 else 00262 error("Broose::handleTimerEvent - no other timer currently in use!"); 00263 }
void Broose::updateTooltip | ( | ) |
updates information shown in tk-environment
00634 { 00635 if (ev.isGUI()) { 00636 std::stringstream ttString; 00637 00638 // show our ip and key in tooltip 00639 ttString << thisNode.ip << " " << thisNode.key; 00640 00641 parentModule()->parentModule()->displayString(). 00642 setTagArg("tt", 0, ttString.str().c_str()); 00643 parentModule()->displayString(). 00644 setTagArg("tt", 0, ttString.str().c_str()); 00645 displayString().setTagArg("tt", 0, ttString.str().c_str()); 00646 00647 } 00648 }
void Broose::handleJoinTimerExpired | ( | cMessage * | msg | ) | [protected] |
handles a expired join timer
msg | the timer self-message |
00266 { 00267 if (protoState == READY) 00268 return; 00269 00270 if (!bootstrapNode.isUnspecified()) { 00271 // create new lookup message 00272 BucketCall* bCallArray[powShiftingBits]; 00273 00274 // do lookups for key >> shiftingBits for each prefix 00275 OverlayKey newKey = thisNode.key >> shiftingBits; 00276 for (int i = 0; i < powShiftingBits; i++) { 00277 OverlayKey add(i); 00278 add = add << (keyLength - shiftingBits); 00279 add += newKey; 00280 00281 bCallArray[i] = new BucketCall("BBucketCall"); 00282 bCallArray[i]->setBucketType(BROTHER); 00283 bCallArray[i]->setBucketIndex(i); 00284 bCallArray[i]->setProState(PINIT); 00285 bCallArray[i]->setLength(BUCKETCALL_L(bCallArray[i])); 00286 00287 // restart join protocol if one call times out 00288 // otherwise the node might be isolated 00289 sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, add, 00290 bCallArray[i]); 00291 } 00292 } else { 00293 // if the bootstrap node is unspecified we are the only node in the network 00294 // so we can skip the "normal" join protocol 00295 changeState(READY); 00296 } 00297 }
void Broose::handleBucketTimerExpired | ( | cMessage * | msg | ) | [protected] |
handles a expired bucket refresh timer
msg | the bucket refresh self-message |
00300 { 00301 BrooseBucket* tmpBucket = new BrooseBucket(); 00302 tmpBucket->initializeBucket (0, 0, thisBrooseNode, 00303 (2*powShiftingBits*rBucketSize + 7*bucketSize), 00304 this); 00305 00306 for (int i = 0; i < powShiftingBits; i++) { 00307 for(uint j = 0; j < rBucket[i]->getSize(); j++) { 00308 if ((simulation.simTime() - rBucket[i]->getLastSeen( 00309 rBucket[i]->get(j))) > refreshTime 00310 || rBucket[i]->getRTT(rBucket[i]->get(j)) == -1) { 00311 00312 tmpBucket->add(BrooseHandle(rBucket[i]->get(j))); 00313 } 00314 } 00315 } 00316 00317 for (uint i = 0; i < lBucket->getSize(); i++) { 00318 if ((simulation.simTime() - lBucket->getLastSeen( 00319 lBucket->get(i))) > refreshTime 00320 || lBucket->getRTT(lBucket->get(i)) == -1) { 00321 00322 tmpBucket->add(BrooseHandle(lBucket->get(i))); 00323 } 00324 } 00325 00326 for (uint i = 0; i < bBucket->getSize(); i++) { 00327 if ((simulation.simTime() - bBucket->getLastSeen( 00328 bBucket->get(i))) > refreshTime 00329 || bBucket->getRTT(bBucket->get(i)) == -1 ) { 00330 00331 tmpBucket->add(BrooseHandle(bBucket->get(i))); 00332 } 00333 } 00334 00335 maxPings = tmpBucket->getSize(); 00336 00337 if (maxPings != 0) { 00338 BroosePingCall** array = new BroosePingCall*[tmpBucket->getSize()]; 00339 00340 for (uint i = 0; i < tmpBucket->getSize(); i++) { 00341 array[i] = new BroosePingCall("PingCall"); 00342 array[i]->setLength(BROOSEPINGCALL_L(array[i])); 00343 00344 sendUdpRpcCall(tmpBucket->get(i), array[i]); 00345 } 00346 } else { 00347 numPings = 0; 00348 scheduleAt(simulation.simTime() + pingDelay, bucket_timer); 00349 } 00350 delete tmpBucket; 00351 }
void Broose::changeState | ( | int | state | ) | [protected] |
changes the node's state
state | the state to which a node is changing |
00112 { 00113 switch (state) { 00114 case INIT: { 00115 protoState = INIT; 00116 00117 if (!refresh) { 00118 // Calculate node's id by hashing its IP address 00119 thisNode.key = OverlayKey::sha1( 00120 const_cast<char*>(thisNode.ip.str().c_str())); 00121 callUpdate(thisNode, true); 00122 thisBrooseNode = BrooseHandle(thisNode); 00123 updateTooltip(); 00124 } else { 00125 removeBootstrapNode(thisNode); 00126 } 00127 00128 // find a new bootstrap node and enroll to the bootstrap list 00129 bootstrapNode = getBootstrapNode(); 00130 00131 cancelEvent(join_timer); 00132 scheduleAt(simulation.simTime(), join_timer); 00133 00134 // initialize respectively clear the buckets 00135 for (int i = 0; i < powShiftingBits; i++) { 00136 rBucket[i]->initializeBucket(shiftingBits, i, 00137 thisBrooseNode, rBucketSize, this); 00138 } 00139 00140 lBucket->initializeBucket(-shiftingBits, 0, thisBrooseNode, 00141 powShiftingBits*rBucketSize, this); 00142 bBucket->initializeBucket(0, 0, thisBrooseNode, 7*bucketSize, 00143 this, true); 00144 00145 // if we have restarted the join protocol reset parameters 00146 refresh = false; 00147 receivedBBucketLookup = 0; 00148 receivedLBucketLookup = 0; 00149 receivedJoinResponse = 0; 00150 00151 assert(parentModule()->parentModule()); 00152 parentModule()->parentModule()->bubble("Enter INIT state."); 00153 break; 00154 } 00155 00156 case RSET: { 00157 protoState = RSET; 00158 00159 BrooseBucket* tmpBucket = new BrooseBucket(); 00160 tmpBucket->initializeBucket(0, 0, thisNode, 00161 powShiftingBits*rBucketSize, this); 00162 00163 for (int i = 0; i < powShiftingBits; i++) { 00164 int size = rBucket[i]->getSize(); 00165 00166 for (int j = 0; j < size; j++) { 00167 tmpBucket->add(rBucket[i]->get(j)); 00168 } 00169 } 00170 00171 BucketCall** bCall = new BucketCall*[tmpBucket->getSize()]; 00172 for (uint i = 0; i < tmpBucket->getSize(); i++) { 00173 bCall[i] = new BucketCall("LBucketCall"); 00174 bCall[i]->setBucketType(LEFT); 00175 bCall[i]->setProState(PRSET); 00176 bCall[i]->setLength(BUCKETCALL_L(bcall[i])); 00177 00178 sendUdpRpcCall(tmpBucket->get(i), bCall[i], numberRetries, 00179 joinDelay); 00180 } 00181 00182 // half of the calls must return to init a state change 00183 numberBBucketLookup = tmpBucket->getSize(); 00184 numberBBucketLookup = (numberBBucketLookup == 1) ? 00185 numberBBucketLookup : (numberBBucketLookup/2); 00186 00187 delete tmpBucket; 00188 00189 assert(parentModule()->parentModule()); 00190 parentModule()->parentModule()->bubble("Enter RSET state."); 00191 break; 00192 } 00193 00194 case BSET: { 00195 protoState = BSET; 00196 00197 // half of the calls must return to init a state change 00198 numberLBucketLookup = bBucket->getSize(); 00199 numberLBucketLookup = (numberLBucketLookup == 1) ? 00200 numberLBucketLookup : (numberLBucketLookup/2); 00201 00202 // send messages to all entries of the B Bucket 00203 int size2 = bBucket->getSize(); 00204 BucketCall** bCall2 = new BucketCall*[size2]; 00205 for (int i = 0; i < size2; i++) { 00206 bCall2[i] = new BucketCall("LBucketCall"); 00207 bCall2[i]->setBucketType(LEFT); 00208 bCall2[i]->setProState(PBSET); 00209 bCall2[i]->setLength(BUCKETCALL_L(bcall2[i])); 00210 00211 sendUdpRpcCall(bBucket->get(i), bCall2[i], numberRetries, 00212 joinDelay); 00213 } 00214 00215 assert(parentModule()->parentModule()); 00216 parentModule()->parentModule()->bubble("Enter BSET state."); 00217 break; 00218 } 00219 00220 case READY: { 00221 protoState = READY; 00222 // registerBootstrapNode(thisNode); 00223 00224 //fill the bucket also with this node 00225 for (int i = 0; i < powShiftingBits; i++) { 00226 rBucket[i]->add(thisBrooseNode); 00227 } 00228 00229 lBucket->add(thisBrooseNode); 00230 bBucket->add(thisBrooseNode); 00231 00232 // to disable the ping protocol a pingDelay or 00233 // refreshTime of zero was given 00234 if (!(pingDelay == 0 || refreshTime == 0)) { 00235 cancelEvent(bucket_timer); 00236 scheduleAt(simulation.simTime() + pingDelay, bucket_timer); 00237 } 00238 00239 assert(parentModule()->parentModule()); 00240 parentModule()->parentModule()->bubble("Enter READY state."); 00241 00242 updateTooltip(); 00243 break; 00244 } 00245 00246 } 00247 setOverlayReady(protoState == READY); 00248 }
NodeVector * Broose::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.
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. |
Reimplemented from BaseOverlay.
00369 { 00370 NodeVector* nextHop = new NodeVector(1); 00371 BrooseFindNodeExtMessage *findNodeExt = NULL; 00372 bool err; 00373 00374 //return the closest nodes 00375 if (isSiblingFor(thisNode, key, numSiblings, &err)) { 00376 BrooseBucket* tmpBBucket = new BrooseBucket(); 00377 BrooseHandle node; 00378 node.key = key; 00379 tmpBBucket->initializeBucket(0, 0, node, bucketSize, this); 00380 int size; 00381 00382 if (bBucket->getSize() > bucketSize) 00383 size = bucketSize; 00384 else 00385 size = bBucket->getSize(); 00386 00387 for (uint i= 0; i < bBucket->getSize();i++) 00388 tmpBBucket->add(bBucket->get(i)); 00389 00390 // todo: this has to be returned, if baselookup can deal 00391 // with the complete vector: 00392 for (int i = 0; i < size; i++) 00393 nextHop->push_back(tmpBBucket->get(i)); 00394 00395 // nextHop->push_back(tmpBBucket->get(0)); 00396 00397 delete tmpBBucket; 00398 return nextHop; 00399 } 00400 00401 if (msg != NULL) { 00402 if (!msg->hasObject("findNodeExt")) { 00403 findNodeExt = new BrooseFindNodeExtMessage("findNodeExt"); 00404 00405 OverlayKey routeKey = thisNode.key; 00406 // estimate distance 00407 int dist = max(rBucket[0]->longestPrefix(), 00408 rBucket[1]->longestPrefix()) + 1 + userDist; 00409 00410 if ((dist % shiftingBits) != 0) 00411 dist += (shiftingBits - (dist % shiftingBits)); 00412 00413 if (dist > keyLength) { 00414 if ((keyLength % shiftingBits) == 0) { 00415 dist = keyLength; 00416 } else { 00417 dist = (keyLength - keyLength % shiftingBits); 00418 } 00419 } 00420 00421 if ((chooseLookup++) % 2 == 0) { 00422 // init left shifting lookup 00423 findNodeExt->setRightShifting(false); 00424 00425 int prefix = 0; 00426 for (int i = 0; i < dist; i++) { 00427 /* prefix += thisNode.key.bitAtPlace(i+1) 00428 (int)pow(2.0, dist - i - 1); */ 00429 prefix += thisNode.key.get(thisNode.key.getLength() - i - 1, 1) << (dist - i - 1); 00430 } 00431 00432 OverlayKey pre(prefix); 00433 routeKey = key >> dist; 00434 routeKey += (pre << key.getLength() - dist); 00435 00436 dist = -dist; 00437 } else { 00438 // init right shifting lookup 00439 findNodeExt->setRightShifting(true); 00440 } 00441 00442 //add contact for next Hop 00443 findNodeExt->setLastNode(thisNode); 00444 findNodeExt->setRouteKey(routeKey); 00445 findNodeExt->setStep(dist); 00446 findNodeExt->setLength(BROOSEFINDNODEEXTMESSAGE_L); 00447 00448 msg->addObject( findNodeExt ); 00449 } 00450 00451 findNodeExt = (BrooseFindNodeExtMessage*) msg->getObject("findNodeExt"); 00452 } 00453 00454 00455 // check for messages which couldn't be routed 00456 if (findNodeExt->getStep() == 0) { 00457 if (!isSiblingFor(thisNode, key, numSiblings, &err)) { 00458 // cout << "Message failed - destKey " << key << "@ simtime " << simulation.simTime() 00459 // << " @node " << thisNode.ip << " lastNode " << findNodeExt->getLastNode().ip << endl; 00460 numFailedPackets++; 00461 } else 00462 error("Broose::findNode - unexpected Error"); 00463 return nextHop; 00464 } 00465 00466 if (findNodeExt->getRightShifting() == false) { 00467 // Left Shifting Lookup 00468 00469 // can't handle left shifting lookup in BSET-State 00470 if (protoState == BSET) 00471 return nextHop; 00472 00473 // update buckets with last hop 00474 addNode(findNodeExt->getLastNode()); 00475 setLastSeen(findNodeExt->getLastNode()); 00476 00477 // replace last hop contact information with 00478 // this hop contact information 00479 findNodeExt->setLastNode(thisNode); 00480 00481 00482 // calculate routing key 00483 findNodeExt->setRouteKey((findNodeExt->getRouteKey()) << shiftingBits); 00484 findNodeExt->setStep(findNodeExt->getStep() + shiftingBits); 00485 00486 // On last hop exchange routeKey for destKey especially 00487 // useful when using lookupNodeIds 00488 NodeHandle nextNode; 00489 00490 if (findNodeExt->getStep() == 0) 00491 nextNode = lBucket->getClosestNode(key); 00492 else 00493 nextNode = lBucket->getClosestNode(findNodeExt->getRouteKey()); 00494 00495 nextHop->push_back(nextNode); 00496 } else { 00497 // Right Shifting Lookup 00498 00499 // update buckets with last hop 00500 addNode(findNodeExt->getLastNode()); 00501 setLastSeen(findNodeExt->getLastNode()); 00502 00503 // replace last hop contact information with 00504 // this hop contact information 00505 findNodeExt->setLastNode(thisNode); 00506 00507 // calculate routing key 00508 int prefix = 0; 00509 int dist = findNodeExt->getStep(); 00510 OverlayKey routeKey = findNodeExt->getRouteKey() >> shiftingBits; 00511 for (int i = 0; i < shiftingBits; i++) 00512 // prefix += key.bitAtPlace(dist-i) * (int) pow (2.0, i); 00513 prefix += key.get(key.getLength() - dist + i, 1) << i; 00514 OverlayKey pre(prefix); 00515 routeKey += (pre << (routeKey.getLength()-shiftingBits)); 00516 00517 findNodeExt->setRouteKey(routeKey); 00518 findNodeExt->setStep(dist - shiftingBits); 00519 00520 // On last hop exchange routeKey for destKey especially 00521 // useful when using lookupNodeIds 00522 NodeHandle nextNode; 00523 00524 if (findNodeExt->getStep() == 0) 00525 nextNode = rBucket[prefix]->getClosestNode(key); 00526 else 00527 nextNode = rBucket[prefix]->getClosestNode(routeKey); 00528 00529 nextHop->push_back(nextNode); 00530 } 00531 00532 if ((*nextHop)[0] == thisNode) { 00533 return (findNode(key, numRedundantNodes, numSiblings, msg)); 00534 } else 00535 return nextHop; 00536 }
bool Broose::keyBelongsToNode | ( | const OverlayKey & | key | ) | [protected] |
decides if a specific key is managed by this node
key | the key |
int Broose::getMaxNumSiblings | ( | ) | [protected, virtual] |
Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.
Reimplemented from BaseOverlay.
00355 { 00356 return bucketSize; 00357 }
int Broose::getMaxNumRedundantNodes | ( | ) | [protected, virtual] |
Query the maximum number of redundant next hop nodes that are returned by findNode().
Reimplemented from BaseOverlay.
00360 { 00361 return bucketSize; 00362 }
void Broose::displayBucketState | ( | ) | [protected] |
debug function which output the content of the node's buckets
00591 { 00592 EV << "[Broose::displayBucketState() @ " << thisNode.ip 00593 << " (" << thisNode.key.toString(16) << ")]" << endl; 00594 for (int i = 0; i < powShiftingBits; i++) { 00595 EV << " Content of rBucket[" << i << "]: "; 00596 rBucket[i]->output(); 00597 } 00598 EV << " Content of lBucket: "; 00599 lBucket->output(); 00600 EV << " Content of bBucket: "; 00601 bBucket->output(); 00602 EV << endl; 00603 }
void Broose::binaryOutput | ( | const OverlayKey & | key | ) | [protected] |
outputs an Overlay key in the binary system
key | the key to output |
00651 { 00652 EV << "[Broose::binaryOutput() @ " << thisNode.ip; 00653 if (key.isUnspecified()) { 00654 EV << " (<unspec>)]" 00655 << endl; 00656 } else { 00657 EV << " ("; 00658 for (unsigned int i = 1; i <= key.getLength(); i++) { 00659 /* EV << key.bitAtPlace(i);*/ 00660 EV << key.get(key.getLength() - i, 1); 00661 } 00662 EV << ")]" << endl; 00663 } 00664 }
void Broose::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
int | rpcId, | |||
simtime_t | rtt | |||
) | [protected, virtual] |
This method is called if an RPC response has been received.
msg | The response message. | |
rpcId | The RPC id. | |
rtt | The Round-Trip-Time of this RPC |
Reimplemented from RpcListener.
00687 { 00688 RPC_SWITCH_START(msg) 00689 RPC_ON_RESPONSE( BroosePing ) { 00690 handleBroosePingResponseRpc(_BroosePingResponse, rtt); 00691 EV << "[Broose::handleRpcResponse() @ " << thisNode.ip 00692 << " (" << thisNode.key.toString(16) << ")]\n" 00693 << " Ping RPC Response received: id=" << rpcId << "\n" 00694 << " msg=" << *_BroosePingResponse << " rtt=" << rtt 00695 << endl; 00696 break; 00697 } 00698 RPC_ON_RESPONSE( Bucket ) { 00699 handleBucketResponseRpc(_BucketResponse); 00700 EV << "[Broose::handleRpcResponse() @ " << thisNode.ip 00701 << " (" << thisNode.key.toString(16) << ")]\n" 00702 << " Bucket RPC Response received: id=" << rpcId << "\n" 00703 << " msg=" << *_BucketResponse << " rtt=" << rtt 00704 << endl; 00705 break; 00706 } 00707 RPC_SWITCH_END( ) 00708 }
void Broose::handleRpcTimeout | ( | BaseCallMessage * | msg, | |
const TransportAddress & | dest, | |||
int | rpcId, | |||
const OverlayKey & | destKey | |||
) | [protected, virtual] |
This method is called if an RPC timeout has been reached.
msg | The original RPC message. | |
dest | The destination node | |
rpcId | The RPC id. | |
destKey | the destination OverlayKey |
Reimplemented from RpcListener.
00712 { 00713 RPC_SWITCH_START(msg) 00714 RPC_ON_CALL( BroosePing ) { 00715 handleBroosePingTimeout(_BroosePingCall, dest, destKey); 00716 EV << "[Broose::handleRpcTimeout() @ " << thisNode.ip 00717 << " (" << thisNode.key.toString(16) << ")]\n" 00718 << " Ping RPC Call timed out: id=" << rpcId << "\n" 00719 << " msg=" << *_BroosePingCall 00720 << endl; 00721 break; 00722 } 00723 RPC_ON_CALL( FindNode ) { 00724 handleFindNodeTimeout(_FindNodeCall, dest, destKey); 00725 EV << "[Broose::handleRpcTimeout() @ " << thisNode.ip 00726 << " (" << thisNode.key.toString(16) << ")]\n" 00727 << " Find Node RPC Call timed out: id=" << rpcId << "\n" 00728 << " msg=" << *_FindNodeCall 00729 << endl; 00730 break; 00731 } 00732 RPC_ON_CALL( Bucket ) { 00733 handleBucketTimeout(_BucketCall); 00734 EV << "[Broose::handleRpcTimeout() @ " << thisNode.ip 00735 << " (" << thisNode.key.toString(16) << ")]\n" 00736 << " Bucket RPC Call timed out: id=" << rpcId << "\n" 00737 << " msg=" << *_BucketCall 00738 << endl; 00739 break; 00740 } 00741 RPC_SWITCH_END( ) 00742 }
void Broose::handleFindNodeTimeout | ( | FindNodeCall * | findNode, | |
const TransportAddress & | dest, | |||
const OverlayKey & | destKey | |||
) | [protected] |
This method is called if an Find Node Call timeout has been reached.
findNode | The original FindNodeCall | |
dest | the destination node | |
destKey | the destination OverlayKey |
00748 { 00749 for (int i = 0; i < powShiftingBits; i++) { 00750 if (rBucket[i]->getFailedResponses(BrooseHandle(dest, destKey)) == numberRetries) 00751 rBucket[i]->remove 00752 (BrooseHandle(dest, destKey)); 00753 else 00754 rBucket[i]->increaseFailedResponses(BrooseHandle(dest, destKey)); 00755 } 00756 00757 if (lBucket->getFailedResponses(BrooseHandle(dest, destKey)) == numberRetries) 00758 lBucket->remove 00759 (BrooseHandle(dest, destKey)); 00760 else 00761 lBucket->increaseFailedResponses(BrooseHandle(dest, destKey)); 00762 00763 if (bBucket->getFailedResponses(BrooseHandle(dest, destKey)) == numberRetries) 00764 bBucket->remove 00765 (BrooseHandle(dest, destKey)); 00766 else 00767 bBucket->increaseFailedResponses(BrooseHandle(dest, destKey)); 00768 }
void Broose::handleBucketRequestRpc | ( | BucketCall * | msg | ) | [protected] |
handles a received Bucket request
msg | the message to process |
00770 { 00771 if (msg->getBucketType() == LEFT) { 00772 // can't handle LBucketRequest in BSET-State 00773 if (protoState == BSET) { 00774 delete msg; 00775 return; 00776 } 00777 00778 // return L-Bucket 00779 int size = lBucket->getSize(); 00780 BucketResponse* bResponse = new BucketResponse("LBucketResponse"); 00781 bResponse->setBucketType(msg->getBucketType()); 00782 bResponse->setProState(msg->getProState()); 00783 bResponse->setNodeNum(size); 00784 bResponse->setNodesArraySize(size); 00785 00786 for (int i = 0; i < size; i++) { 00787 bResponse->setNodes(i, lBucket->get(i)); 00788 } 00789 00790 bResponse->setLength(BUCKETRESPONSE_L(bResponse)); 00791 00792 addNode(msg->getSrcNode()); 00793 setLastSeen(msg->getSrcNode()); 00794 00795 sendRpcResponse(msg, bResponse ); 00796 } else if(msg->getBucketType() == BROTHER) { 00797 // return B-Bucket 00798 int size = bBucket->getSize(); 00799 BucketResponse* bResponse = new BucketResponse("BBucketResponse"); 00800 bResponse->setBucketType(msg->getBucketType()); 00801 bResponse->setBucketIndex(msg->getBucketIndex()); 00802 bResponse->setProState(msg->getProState()); 00803 bResponse->setNodeNum(size); 00804 bResponse->setNodesArraySize(size); 00805 00806 for (int i = 0; i < size; i++) { 00807 bResponse->setNodes(i, bBucket->get(i)); 00808 } 00809 bResponse->setLength(BUCKETRESPONSE_L(bResponse)); 00810 00811 sendRpcResponse(msg, bResponse ); 00812 } else 00813 error("Broose::handleBucketRequestRpc() - Wrong Bucket Type!"); 00814 }
void Broose::handleBucketResponseRpc | ( | BucketResponse * | msg | ) | [protected] |
handles a received Bucket response
msg | the message to process |
00817 { 00818 if (msg->getBucketType() == LEFT) { 00819 switch (protoState) { 00820 case RSET: 00821 if (msg->getProState() == PRSET) { 00822 for (int i = 0; i < msg->getNodeNum(); i++) { 00823 bBucket->add(BrooseHandle(msg->getNodes(i))); 00824 } 00825 receivedBBucketLookup++; 00826 00827 if (receivedBBucketLookup == numberBBucketLookup) 00828 changeState(BSET); 00829 } 00830 break; 00831 case BSET: 00832 if (msg->getProState() == PBSET) { 00833 for (int i = 0; i < msg->getNodeNum(); i++) { 00834 lBucket->add(BrooseHandle(msg->getNodes(i))); 00835 } 00836 receivedLBucketLookup++; 00837 00838 if(receivedLBucketLookup == numberLBucketLookup) 00839 changeState(READY); 00840 } 00841 break; 00842 } 00843 } else if(msg->getBucketType() == BROTHER) { 00844 switch(protoState) { 00845 case INIT: 00846 if (msg->getProState() == PINIT) { 00847 int k = msg->getBucketIndex(); 00848 00849 for (int i = 0; i < msg->getNodeNum(); i++) { 00850 rBucket[k]->add(msg->getNodes(i)); 00851 } 00852 00853 receivedJoinResponse++; 00854 if (receivedJoinResponse == powShiftingBits) 00855 changeState(RSET); 00856 } 00857 } 00858 } else 00859 error("Broose::handleBucketRequestRpc() - unknown error."); 00860 }
void Broose::handleBucketTimeout | ( | BucketCall * | msg | ) | [protected] |
handles a received Bucket timeout
msg | the message to process |
00864 { 00865 if (protoState == READY) 00866 return; 00867 else { 00868 refresh = true; 00869 changeState(INIT); 00870 } 00871 }
void Broose::handleBroosePingRequestRpc | ( | BroosePingCall * | msg | ) | [protected] |
handles a received Ping request
msg | the message to process |
00875 { 00876 BroosePingResponse* pingResponse = new BroosePingResponse("PingResponse"); 00877 pingResponse->setLength(BROOSEPINGRESPONSE_L(pingResponse)); 00878 00879 // add pinging node to all buckets and update lastSeen of node 00880 addNode(msg->getSrcNode()); 00881 setLastSeen(msg->getSrcNode()); 00882 00883 sendRpcResponse(msg, pingResponse); 00884 }
void Broose::handleBroosePingResponseRpc | ( | BroosePingResponse * | msg, | |
simtime_t | rtt | |||
) | [protected] |
handles a received Ping response
msg | the message to process | |
rtt | the round trip time of the message |
00888 { 00889 // if node respond reset failedResponses and add lastSeen to node 00890 setLastSeen(msg->getSrcNode()); 00891 resetFailedResponses(msg->getSrcNode()); 00892 setRTT(msg->getSrcNode(), rtttime); 00893 00894 numPings++; 00895 00896 if (numPings == maxPings) { 00897 numPings = 0; 00898 scheduleAt(simulation.simTime() + pingDelay, bucket_timer); 00899 } 00900 }
void Broose::handleBroosePingTimeout | ( | BroosePingCall * | msg, | |
const TransportAddress & | dest, | |||
const OverlayKey & | destKey | |||
) | [protected] |
handles a received Ping timeout
msg | the message to process | |
dest | the destination node | |
destKey | the destination OverlayKey |
00905 { 00906 for (int i = 0; i < powShiftingBits; i++) { 00907 if (rBucket[i]->getFailedResponses(BrooseHandle(dest, destKey)) == numberRetries) 00908 rBucket[i]->remove(BrooseHandle(dest, destKey)); 00909 else 00910 rBucket[i]->increaseFailedResponses(BrooseHandle(dest, destKey)); 00911 } 00912 00913 if (lBucket->getFailedResponses(BrooseHandle(dest, destKey)) == numberRetries) { 00914 lBucket->remove(BrooseHandle(dest, destKey)); 00915 } else { 00916 lBucket->increaseFailedResponses(BrooseHandle(dest, destKey)); 00917 } 00918 00919 if (bBucket->getFailedResponses(BrooseHandle(dest, destKey)) == numberRetries) { 00920 bBucket->remove(BrooseHandle(dest, destKey)); 00921 } else { 00922 bBucket->increaseFailedResponses(BrooseHandle(dest, destKey)); 00923 } 00924 00925 numPings++; 00926 00927 if (numPings == maxPings) { 00928 numPings = 0; 00929 scheduleAt(simulation.simTime() + pingDelay, bucket_timer); 00930 } 00931 }
void Broose::setLastSeen | ( | NodeHandle | node | ) | [protected] |
updates the timestamp of a node in all buckets
node | node handle which should be updated |
00934 { 00935 for (int i = 0; i < powShiftingBits; i++) { 00936 rBucket[i]->setLastSeen(BrooseHandle(node), simulation.simTime()); 00937 } 00938 00939 lBucket->setLastSeen(BrooseHandle(node), simulation.simTime()); 00940 bBucket->setLastSeen(BrooseHandle(node), simulation.simTime()); 00941 }
void Broose::addNode | ( | NodeHandle | node, | |
int | bucket = 0 | |||
) | [protected] |
adds a node to all buckets
node | node handle which should be added | |
bucket | reserved |
00944 { 00945 if (bucket == 0) { 00946 // add node to all buckets 00947 for (int i = 0; i < powShiftingBits; i++) { 00948 rBucket[i]->add 00949 (BrooseHandle(node)); 00950 } 00951 00952 lBucket->add(BrooseHandle(node)); 00953 bBucket->add(BrooseHandle(node)); 00954 } else 00955 error("Broose::addNode() - not implemented"); 00956 }
void Broose::resetFailedResponses | ( | NodeHandle | node | ) | [protected] |
resets the counter of failed responses
node | node handle of the responding node |
00959 { 00960 for (int i = 0; i < powShiftingBits; i++) { 00961 rBucket[i]->resetFailedResponses(BrooseHandle(node)); 00962 } 00963 00964 lBucket->resetFailedResponses(BrooseHandle(node)); 00965 bBucket->resetFailedResponses(BrooseHandle(node)); 00966 }
void Broose::setRTT | ( | NodeHandle | node, | |
simtime_t | rtt | |||
) | [protected] |
sets the rtt to a node in all buckets
node | node handle to which a rtt is added/updated | |
rtt | round trip time to the node |
00969 { 00970 for (int i = 0; i < powShiftingBits; i++) { 00971 rBucket[i]->setRTT(BrooseHandle(node), rtttime); 00972 } 00973 00974 lBucket->setRTT(BrooseHandle(node), rtttime); 00975 bBucket->setRTT(BrooseHandle(node), rtttime); 00976 }
friend class BrooseBucket [friend] |
int Broose::chooseLookup [protected] |
decides which kind of lookup (right/left shifting) is used
int Broose::joinDelay [protected] |
time interval between two join tries
int Broose::protoState [protected] |
the state in which a node currently is
int Broose::receivedJoinResponse [protected] |
number of received join response messages
int Broose::receivedBBucketLookup [protected] |
number of received lookup responses for the B bucket
int Broose::numberBBucketLookup [protected] |
maximal number of lookup reponses for the B bucket
int Broose::receivedLBucketLookup [protected] |
number of received lookup responses for the L bucket
int Broose::numberLBucketLookup [protected] |
maximal number of lookup reponses for the L bucket
int Broose::shiftingBits [protected] |
number of bits shifted in/out each step
int Broose::powShiftingBits [protected] |
2^{variable shiftingBits}
uint Broose::bucketSize [protected] |
maximal number of bucket entries
uint Broose::rBucketSize [protected] |
maximal number of entries in the r buckets
int Broose::parallelRequests [protected] |
number ob parallel requests
int Broose::keyLength [protected] |
length of the node and data IDs
bool Broose::refresh [protected] |
is the node restarting the bootstrap protocol or is it a new node
int Broose::pingDelay [protected] |
time intervall between bucket refreshs
int Broose::refreshTime [protected] |
time intervall after which a ping is done
uint Broose::userDist [protected] |
how many hops are added to the estimated hop count
int Broose::numPings [protected] |
actual number of received ping messages
int Broose::maxPings [protected] |
total number of ping messages
int Broose::numberRetries [protected] |
number of retries in case of timeout
int Broose::bucketCount [protected] |
number of Bucket messages
int Broose::bucketBytesSent [protected] |
length of all Bucket messages
int Broose::broosePingCount [protected] |
number of Ping messages
int Broose::broosePingBytesSent [protected] |
length of all Ping messages
int Broose::numFailedPackets [protected] |
number of packets which couldn't be routed correctly
BrooseBucket* Broose::lBucket [protected] |
BrooseBucket * Broose::bBucket [protected] |
BrooseBucket** Broose::rBucket [protected] |
cMessage* Broose::join_timer [protected] |
cMessage* Broose::bucket_timer [protected] |
timer to reconstruct all buckets
NodeHandle Broose::bootstrapNode [protected] |
node handle holding the bootstrap node
BrooseHandle Broose::thisBrooseNode [protected] |
this is a BrooseHandle of the current node like thisNode