Broose.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2007 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include "Broose.h"
00025 #include <RpcMacros.h>
00026 #include <GlobalStatistics.h>
00027 #include <IPAddressResolver.h>
00028 #include <BootstrapList.h>
00029 #include <LookupListener.h>
00030 
00031 using namespace std;
00032 
00033 Define_Module(Broose);
00034 
00035 class BrooseLookupListener : public LookupListener
00036 {
00037 private:
00038     Broose* overlay;
00039 public:
00040     BrooseLookupListener(Broose* overlay)
00041     {
00042         this->overlay = overlay;
00043     }
00044 
00045     virtual void lookupFinished(AbstractLookup *lookup)
00046     {
00047         delete this;
00048     }
00049 };
00050 
00051 Broose::Broose()
00052 {
00053     join_timer = NULL;
00054     bucket_timer = NULL;
00055     rBucket = NULL;
00056     lBucket = NULL;
00057     bBucket =  NULL;
00058 }
00059 Broose::~Broose()
00060 {
00061     // delete timers
00062     cancelAndDelete(join_timer);
00063     cancelAndDelete(bucket_timer);
00064 }
00065 
00066 void Broose::initializeOverlay(int stage)
00067 {
00068     // because of IPAddressResolver, we need to wait until interfaces
00069     // are registered, address auto-assignment takes place etc.
00070     if (stage != MIN_STAGE_OVERLAY)
00071         return;
00072 
00073     // Broose provides KBR services
00074     kbr = true;
00075 
00076     // fetch some parameters
00077     bucketSize = par("bucketSize"); // = k
00078     rBucketSize = par("rBucketSize"); // = k'
00079     joinDelay = par("joinDelay");
00080     shiftingBits = par("brooseShiftingBits");
00081     userDist = par("userDist");
00082     refreshTime = par("refreshTime");
00083     numberRetries = par("numberRetries");
00084 
00085     //statistics
00086     bucketCount = 0;
00087     bucketBytesSent = 0;
00088 
00089     //init local parameters
00090     chooseLookup = 0;
00091     receivedJoinResponse = 0;
00092     receivedBBucketLookup = 0;
00093     numberBBucketLookup = 0;
00094     receivedLBucketLookup = 0;
00095     numberLBucketLookup = 0;
00096     powShiftingBits = 1 << shiftingBits;
00097     keyLength = OverlayKey::getLength();
00098     numFailedPackets = 0;
00099     bucketRetries = 0;
00100 
00101     // add some watches
00102     WATCH(receivedJoinResponse);
00103     WATCH(receivedBBucketLookup);
00104     WATCH(numberBBucketLookup);
00105     WATCH(receivedLBucketLookup);
00106     WATCH(numberLBucketLookup);
00107     WATCH(state);
00108 
00109     // get module pointers for all buckets
00110     rBucket = new BrooseBucket*[powShiftingBits];
00111 
00112     for (int i = 0; i < powShiftingBits; i++) {
00113         rBucket[i] = check_and_cast<BrooseBucket*>
00114                      (getParentModule()->getSubmodule("rBucket",i));
00115         bucketVector.push_back(rBucket[i]);
00116     }
00117 
00118     lBucket = check_and_cast<BrooseBucket*>
00119               (getParentModule()->getSubmodule("lBucket"));
00120     bucketVector.push_back(lBucket);
00121 
00122     bBucket = check_and_cast<BrooseBucket*>
00123               (getParentModule()->getSubmodule("bBucket"));
00124     bucketVector.push_back(bBucket);
00125 
00126     // create join and bucket timer
00127     join_timer = new cMessage("join_timer");
00128     bucket_timer = new cMessage("bucket_timer");
00129 }
00130 
00131 void Broose::joinOverlay()
00132 {
00133     changeState(INIT);
00134 
00135     // if the bootstrap node is unspecified we are the only node in the network
00136     // so we can skip the "normal" join protocol
00137     if (bootstrapNode.isUnspecified()) {
00138         changeState(READY);
00139     }
00140 }
00141 
00142 
00143 void Broose::changeState(int toState)
00144 {
00145     switch (toState) {
00146     case INIT: {
00147         state = INIT;
00148 
00149         // find a new bootstrap node and enroll to the bootstrap list
00150         bootstrapNode = bootstrapList->getBootstrapNode();
00151 
00152         cancelEvent(join_timer);
00153         scheduleAt(simTime(), join_timer);
00154 
00155         // initialize respectively clear the buckets
00156         for (int i = 0; i < powShiftingBits; i++) {
00157             rBucket[i]->initializeBucket(shiftingBits, i, rBucketSize, this);
00158         }
00159 
00160         lBucket->initializeBucket(-shiftingBits, 0, powShiftingBits*rBucketSize,
00161                                   this);
00162         bBucket->initializeBucket(0, 0, 7*bucketSize, this, true);
00163 
00164         // if we have restarted the join protocol reset parameters
00165         receivedBBucketLookup = 0;
00166         receivedLBucketLookup = 0;
00167         receivedJoinResponse = 0;
00168 
00169         getParentModule()->getParentModule()->bubble("Enter INIT state.");
00170         updateTooltip();
00171         break;
00172     }
00173 
00174     case RSET: {
00175         state = RSET;
00176 
00177         BrooseBucket* tmpBucket = new BrooseBucket();
00178         tmpBucket->initializeBucket(0, 0, powShiftingBits*rBucketSize, this);
00179 
00180         for (int i = 0; i < powShiftingBits; i++) {
00181             int size = rBucket[i]->getSize();
00182 
00183             for (int j = 0; j < size; j++) {
00184                 tmpBucket->add(rBucket[i]->get(j));
00185             }
00186         }
00187 
00188         BucketCall** bCall = new BucketCall*[tmpBucket->getSize()];
00189         for (uint32_t i = 0; i < tmpBucket->getSize(); i++) {
00190             bCall[i] = new BucketCall("LBucketCall");
00191             bCall[i]->setBucketType(LEFT);
00192             bCall[i]->setProState(PRSET);
00193             bCall[i]->setBitLength(BUCKETCALL_L(bcall[i]));
00194 
00195             sendUdpRpcCall(tmpBucket->get(i), bCall[i], NULL,
00196                            10);
00197         }
00198 
00199         // half of the calls must return for a state change
00200         numberBBucketLookup = ceil((double)tmpBucket->getSize() / 2);
00201 
00202         delete tmpBucket;
00203 
00204         getParentModule()->getParentModule()->bubble("Enter RSET state.");
00205         break;
00206     }
00207 
00208     case BSET: {
00209         state = BSET;
00210 
00211         // half of the calls must return for a state change
00212         numberLBucketLookup = ceil((double)bBucket->getSize() / 2);
00213 
00214         // send messages to all entries of the B Bucket
00215         int size2 = bBucket->getSize();
00216         BucketCall** bCall2 = new BucketCall*[size2];
00217         for (int i = 0; i < size2; i++) {
00218             bCall2[i] = new BucketCall("LBucketCall");
00219             bCall2[i]->setBucketType(LEFT);
00220             bCall2[i]->setProState(PBSET);
00221             bCall2[i]->setBitLength(BUCKETCALL_L(bcall2[i]));
00222 
00223             sendUdpRpcCall(bBucket->get(i), bCall2[i], NULL,
00224                            10);
00225         }
00226 
00227         getParentModule()->getParentModule()->bubble("Enter BSET state.");
00228         break;
00229     }
00230 
00231     case READY: {
00232         state = READY;
00233 
00234         // fill the bucket also with this node
00235         for (size_t i = 0; i < bucketVector.size(); i++) {
00236             bucketVector[i]->add(thisNode);
00237         }
00238 
00239         // to disable the ping protocol a pingDelay or
00240         // refreshTime of zero was given
00241         if (refreshTime != 0) {
00242             cancelEvent(bucket_timer);
00243             scheduleAt(simTime() + (refreshTime / 2.0), bucket_timer);
00244         }
00245 
00246         getParentModule()->getParentModule()->bubble("Enter READY state.");
00247 
00248         updateTooltip();
00249         break;
00250     }
00251 
00252     }
00253     setOverlayReady(state == READY);
00254 }
00255 
00256 void Broose::handleTimerEvent(cMessage* msg)
00257 {
00258     if (msg == join_timer)
00259         handleJoinTimerExpired(msg);
00260     else if (msg == bucket_timer)
00261         handleBucketTimerExpired(msg);
00262     else
00263         error("Broose::handleTimerEvent - no other timer currently in use!");
00264 }
00265 
00266 void Broose::handleJoinTimerExpired(cMessage* msg)
00267 {
00268     if (state == READY)
00269         return;
00270 
00271     if (!bootstrapNode.isUnspecified()) {
00272         // create new lookup message
00273 #if 0
00274         BucketCall* bCall = new BucketCall();
00275         bCall->setBucketType(BROTHER);
00276         bCall->setProState(FAILED);
00277         bCall->setBitLength(BUCKETCALL_L(call));
00278         sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, thisNode.getKey(),
00279                          bCall);
00280 
00281         BucketCall* lCall = new BucketCall();
00282         lCall->setBucketType(BROTHER);
00283         lCall->setProState(FAILED);
00284         lCall->setBitLength(BUCKETCALL_L(call));
00285         sendRouteRpcCall(OVERLAY_COMP, bootstrapNode,
00286                          thisNode.getKey() << shiftingBits, lCall);
00287 #endif
00288         // do lookups for key >> shiftingBits for each prefix
00289         OverlayKey newKey = thisNode.getKey() >> shiftingBits;
00290         BucketCall* bCallArray[powShiftingBits];
00291         for (int i = 0; i < powShiftingBits; i++) {
00292             OverlayKey add(i);
00293             add = add << (keyLength - shiftingBits);
00294             add += newKey;
00295 
00296             bCallArray[i] = new BucketCall("BBucketCall");
00297             bCallArray[i]->setBucketType(BROTHER);
00298             bCallArray[i]->setBucketIndex(i);
00299             bCallArray[i]->setProState(PINIT);
00300             bCallArray[i]->setBitLength(BUCKETCALL_L(bCallArray[i]));
00301 
00302             // restart join protocol if one call times out
00303             // otherwise the node might be isolated
00304             sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, add,
00305                              bCallArray[i]);
00306         }
00307         //createLookup()->lookup(getThisNode().getKey() + 1, 0, 0, 0,
00308         //                       new BrooseLookupListener(this));
00309     } else {
00310         // if the bootstrap node is unspecified we are the only node in the network
00311         // so we can skip the "normal" join protocol
00312         changeState(READY);
00313     }
00314 }
00315 
00316 void Broose::handleBucketTimerExpired(cMessage* msg)
00317 {
00318     BrooseBucket* tmpBucket = new BrooseBucket();
00319     tmpBucket->initializeBucket(0, 0,
00320                                 (2*powShiftingBits*rBucketSize + 7*bucketSize),
00321                                 this);
00322 
00323     for (size_t i = 0; i < bucketVector.size(); i++) {
00324         for(uint32_t j = 0; j < bucketVector[i]->getSize(); j++) {
00325             if ((simTime() - bucketVector[i]->getLastSeen(
00326                         bucketVector[i]->get(j))) > refreshTime
00327                     || bucketVector[i]->getRTT(bucketVector[i]->get(j)) == -1) {
00328 
00329                 tmpBucket->add(BrooseHandle(bucketVector[i]->get(j)));
00330             }
00331         }
00332     }
00333 
00334     for (uint32_t i = 0; i < tmpBucket->getSize(); i++) {
00335         pingNode(tmpBucket->get(i));
00336     }
00337 
00338     delete tmpBucket;
00339 
00340     scheduleAt(simTime() + (refreshTime / 2.0), bucket_timer);
00341 }
00342 
00343 
00344 int Broose::getMaxNumSiblings()
00345 {
00346     return bucketSize;
00347 }
00348 
00349 int Broose::getMaxNumRedundantNodes()
00350 {
00351     return bucketSize;
00352 }
00353 
00354 int Broose::getRoutingDistance(const OverlayKey& key, const OverlayKey& node,
00355                                int dist)
00356 {
00357     for (uint i = 0; i < (uint)abs(dist); i++) {
00358         if (node.sharedPrefixLength(key << i) >= (abs(dist) - i)) {
00359              return i; // right shifting
00360          }
00361         if (key.sharedPrefixLength(node << i) >= (abs(dist) - i)) {
00362             return -i; // left shifting
00363         }
00364     }
00365 
00366     if (((chooseLookup++) % 2) == 0) {
00367         return -dist;
00368     } else {
00369         return dist;
00370     }
00371 }
00372 
00373 #if 0
00374 // TODO: work in progress: new findNode() code which tries to calculate
00375 //       the distance approximation and new routing key in each routing step
00376 NodeVector* Broose::findNode(const OverlayKey& key,
00377                              int numRedundantNodes,
00378                              int numSiblings,
00379                              BaseOverlayMessage* msg)
00380 {
00381     BrooseFindNodeExtMessage *findNodeExt = NULL;
00382     bool err;
00383     bool isSibling = isSiblingFor(thisNode, key, numSiblings, &err);
00384     int resultSize;
00385 
00386     if (numSiblings < 0) {
00387         // exhaustive iterative doesn't care about siblings
00388         resultSize = numRedundantNodes;
00389     } else {
00390         resultSize = isSibling ? (numSiblings ? numSiblings : 1)
00391                                                       : numRedundantNodes;
00392     }
00393     assert(numSiblings || numRedundantNodes);
00394     NodeVector* result = new NodeVector(resultSize);
00395 
00396     if (isSibling) {
00397         //return the closest nodes
00398         // sort with XOR distance to key
00399         KeyDistanceComparator<KeyXorMetric>* comp =
00400             new KeyDistanceComparator<KeyXorMetric>(key);
00401         result->setComparator(comp);
00402 
00403         bBucket->fillVector(result);
00404         result->add(thisNode);
00405 
00406         delete comp;
00407 
00408 
00409         std::cout << "key: " << key.toString(2).substr(0, 8)
00410                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00411         if (result->size() > 0) {
00412             std::cout << " next hop (final): " << (*result)[0].getKey().toString(2).substr(0, 8);
00413         } else {
00414             std::cout << " no next hop! (final)";
00415         }
00416         std::cout << std::endl << std::endl;
00417 
00418 
00419         return result;
00420     }
00421 
00422     // estimate distance
00423     int dist = max(rBucket[0]->longestPrefix(),
00424                    rBucket[1]->longestPrefix()) + 1 + userDist;
00425 
00426     if ((dist % shiftingBits) != 0)
00427         dist += (shiftingBits - (dist % shiftingBits));
00428 
00429     if (dist > keyLength) {
00430         if ((keyLength % shiftingBits) == 0) {
00431             dist = keyLength;
00432         } else {
00433             dist = (keyLength - keyLength % shiftingBits);
00434         }
00435     }
00436 
00437     if (msg != NULL) {
00438         if (!msg->hasObject("findNodeExt")) {
00439             findNodeExt = new BrooseFindNodeExtMessage("findNodeExt");
00440 
00441             findNodeExt->setMaxDistance(dist);
00442 
00443             //add contact for next Hop
00444             findNodeExt->setLastNode(thisNode);
00445             findNodeExt->setBitLength(BROOSEFINDNODEEXTMESSAGE_L);
00446 
00447             msg->addObject( findNodeExt );
00448         }
00449 
00450         findNodeExt = (BrooseFindNodeExtMessage*) msg->getObject("findNodeExt");
00451     }
00452 
00453     // update buckets with last hop
00454     routingAdd(findNodeExt->getLastNode(), true);
00455 
00456     // replace last hop contact information with
00457     // this hop contact information
00458     findNodeExt->setLastNode(thisNode);
00459 
00460     //findNodeExt->setMaxDistance(max(findNodeExt->getMaxDistance(), dist));
00461 
00462     int step = getRoutingDistance(key, thisNode.getKey(),
00463                                   findNodeExt->getMaxDistance());
00464 
00465     bool leftShifting;
00466     if (step < 0) {
00467         leftShifting = true;
00468         step *= -1;
00469     }
00470 
00471     if ((step % shiftingBits) != 0)
00472         step += (shiftingBits - (step % shiftingBits));
00473 
00474     if (step > keyLength) {
00475         if ((keyLength % shiftingBits) == 0) {
00476             step = keyLength;
00477         } else {
00478             step = (keyLength - keyLength % shiftingBits);
00479         }
00480     }
00481 
00482     if (leftShifting) {
00483         step *= -1;
00484     }
00485 
00486     // check for messages which couldn't be routed
00487     if (step == 0) {
00488         //return the closest nodes
00489         // sort with XOR distance to key
00490         KeyDistanceComparator<KeyXorMetric>* comp =
00491             new KeyDistanceComparator<KeyXorMetric>(key);
00492         result->setComparator(comp);
00493 
00494         bBucket->fillVector(result);
00495         result->add(thisNode);
00496 
00497 
00498         std::cout << "key: " << key.toString(2).substr(0, 8)
00499                   << " dist: " << step << " (max: " << findNodeExt->getMaxDistance() << ")"
00500                   << " rtkey: " << thisNode.getKey().toString(2).substr(0, 8)
00501                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00502         if (result->size() > 0) {
00503             std::cout << " next hop: " << (*result)[0].getKey().toString(2).substr(0, 8);
00504         } else {
00505             std::cout << " no next hop!";
00506         }
00507         std::cout << std::endl << std::endl;
00508 
00509 
00510         delete comp;
00511         return result;
00512     } else if (step < 0) {
00513         if (state == BSET) {
00514             return result;
00515         }
00516         // Left Shifting Lookup
00517         OverlayKey routingKey = key >> (-step - 1);
00518         for (int i = 0; i < (-step - 1); i++) {
00519             routingKey.setBit(OverlayKey::getLength() - i - 1,
00520                               thisNode.getKey().getBit(
00521                               OverlayKey::getLength() - i - 2));
00522         }
00523 
00524         KeyDistanceComparator<KeyXorMetric>* comp =
00525             new KeyDistanceComparator<KeyXorMetric>(routingKey);
00526 
00527         result->setComparator(comp);
00528         lBucket->fillVector(result);
00529         result->add(thisNode);
00530         delete comp;
00531 
00532         std::cout << "key: " << key.toString(2).substr(0, 8)
00533                   << " dist: " << step << " (max: " << findNodeExt->getMaxDistance() << ")"
00534                   << " rtkey: " << routingKey.toString(2).substr(0, 8)
00535                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00536         if (result->size() > 0) {
00537             std::cout << " next hop: " << (*result)[0].getKey().toString(2).substr(0, 8);
00538         } else {
00539             std::cout << " no next hop!";
00540         }
00541         std::cout << std::endl << std::endl;
00542 
00543 
00544     } else {
00545         // Right Shifting Lookup
00546         KeyDistanceComparator<KeyXorMetric>* comp = NULL;
00547             comp = new KeyDistanceComparator<KeyXorMetric>(key << (step - shiftingBits));
00548 
00549         result->setComparator(comp);
00550         rBucket[key.getBitRange(key.getLength() - step - 1,
00551                                 shiftingBits)]->fillVector(result);
00552         result->add(thisNode);
00553         delete comp;
00554 
00555         std::cout << "key: " << key.toString(2).substr(0, 8)
00556                   << " dist: " << step << " (max: " << findNodeExt->getMaxDistance() << ")"
00557                   << " rtkey: " << (key >> step).toString(2).substr(0, 8)
00558                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00559         if (result->size() > 0) {
00560             std::cout << " next hop: " << (*result)[0].getKey().toString(2).substr(0, 8);
00561         } else {
00562             std::cout << " no next hop!";
00563         }
00564         std::cout << std::endl << std::endl;
00565 
00566     }
00567 
00568     return result;
00569 }
00570 #endif
00571 
00572 NodeVector* Broose::findNode(const OverlayKey& key,
00573                              int numRedundantNodes,
00574                              int numSiblings,
00575                              BaseOverlayMessage* msg)
00576 {
00577     if ((state == INIT) || (state == RSET) || (state == FAILED))
00578         return new NodeVector();
00579 
00580     BrooseFindNodeExtMessage *findNodeExt = NULL;
00581     bool err;
00582     bool isSibling = isSiblingFor(thisNode, key, numSiblings, &err);
00583     int resultSize;
00584 
00585     if (numSiblings < 0) {
00586         // exhaustive iterative doesn't care about siblings
00587         resultSize = numRedundantNodes;
00588     } else {
00589         resultSize = isSibling ? (numSiblings ? numSiblings : 1)
00590                                                       : numRedundantNodes;
00591     }
00592     assert(numSiblings || numRedundantNodes);
00593     NodeVector* result = new NodeVector(resultSize);
00594 
00595     if (isSibling) {
00596         //return the closest nodes
00597         // sort with XOR distance to key
00598         KeyDistanceComparator<KeyXorMetric>* comp =
00599             new KeyDistanceComparator<KeyXorMetric>(key);
00600         result->setComparator(comp);
00601 
00602         bBucket->fillVector(result);
00603         result->add(thisNode);
00604 
00605         delete comp;
00606 
00607         /*
00608         std::cout << "key: " << key.toString(2).substr(0, 8)
00609                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00610         if (result->size() > 0) {
00611             std::cout << " next hop (final): " << (*result)[0].getKey().toString(2).substr(0, 8);
00612         } else {
00613             std::cout << " no next hop! (final)";
00614         }
00615         std::cout << std::endl << std::endl;
00616         */
00617 
00618         return result;
00619     }
00620 
00621     if (msg != NULL) {
00622         if (!msg->hasObject("findNodeExt")) {
00623             findNodeExt = new BrooseFindNodeExtMessage("findNodeExt");
00624 
00625             OverlayKey routeKey = thisNode.getKey();
00626             // estimate distance
00627             int dist = max(rBucket[0]->longestPrefix(),
00628                            rBucket[1]->longestPrefix()) + 1 + userDist;
00629 
00630             if ((dist % shiftingBits) != 0)
00631                 dist += (shiftingBits - (dist % shiftingBits));
00632 
00633             if (dist > keyLength) {
00634                 if ((keyLength % shiftingBits) == 0) {
00635                     dist = keyLength;
00636                 } else {
00637                     dist = (keyLength - keyLength % shiftingBits);
00638                 }
00639             }
00640 
00641             if ((chooseLookup++) % 2 == 0) {
00642                 // init left shifting lookup
00643                 findNodeExt->setRightShifting(false);
00644 
00645                 int prefix = 0;
00646                 for (int i = 0; i < dist; i++) {
00647                     prefix += thisNode.getKey().getBit(thisNode.getKey().getLength() - i - 1) << (dist - i - 1);
00648                 }
00649 
00650                 OverlayKey pre(prefix);
00651                 routeKey = key >> dist;
00652                 routeKey += (pre << key.getLength() - dist);
00653 
00654                 dist = -dist;
00655             } else {
00656                 // init right shifting lookup
00657                 findNodeExt->setRightShifting(true);
00658             }
00659 
00660             //add contact for next Hop
00661             findNodeExt->setLastNode(thisNode);
00662             findNodeExt->setRouteKey(routeKey);
00663             findNodeExt->setStep(dist);
00664             findNodeExt->setBitLength(BROOSEFINDNODEEXTMESSAGE_L);
00665 
00666             msg->addObject( findNodeExt );
00667         }
00668 
00669         findNodeExt = (BrooseFindNodeExtMessage*) msg->getObject("findNodeExt");
00670     }
00671 
00672     // update buckets with last hop
00673     addNode(findNodeExt->getLastNode());
00674     setLastSeen(findNodeExt->getLastNode());
00675 
00676     // replace last hop contact information with
00677     // this hop contact information
00678     findNodeExt->setLastNode(thisNode);
00679 
00680     // brother lookup
00681     if (findNodeExt->getStep() == 0) {
00682         // return the closest nodes sorted by XOR distance to key
00683         KeyDistanceComparator<KeyXorMetric>* comp =
00684             new KeyDistanceComparator<KeyXorMetric>(key);
00685         result->setComparator(comp);
00686 
00687         bBucket->fillVector(result);
00688         result->add(thisNode);
00689 
00690         delete comp;
00691         return result;
00692     }
00693 
00694     if (findNodeExt->getRightShifting() == false) {
00695         // Left Shifting Lookup
00696 
00697         // can't handle left shifting lookup in BSET-State
00698         if (state == BSET)
00699             return result;
00700 
00701         // calculate routing key
00702         findNodeExt->setRouteKey((findNodeExt->getRouteKey()) << shiftingBits);
00703         findNodeExt->setStep(findNodeExt->getStep() + shiftingBits);
00704 
00705         KeyDistanceComparator<KeyXorMetric>* comp = NULL;
00706         comp = new KeyDistanceComparator<KeyXorMetric>(
00707                 findNodeExt->getRouteKey());
00708 
00709         result->setComparator(comp);
00710         lBucket->fillVector(result);
00711         result->add(thisNode);
00712         delete comp;
00713         /*
00714         std::cout << "key: " << key.toString(2).substr(0, 8)
00715                   << " dist: " << findNodeExt->getStep()
00716                   << " rtkey: " << findNodeExt->getRouteKey().toString(2).substr(0, 8)
00717                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00718         if (result->size() > 0) {
00719             std::cout << " next hop: " << (*result)[0].getKey().toString(2).substr(0, 8);
00720         } else {
00721             std::cout << " no next hop!";
00722         }
00723         std::cout << std::endl << std::endl;
00724         */
00725 
00726     } else {
00727         // Right Shifting Lookup
00728 
00729 
00730         // calculate routing key
00731         int prefix = 0;
00732         int dist = findNodeExt->getStep();
00733         OverlayKey routeKey = findNodeExt->getRouteKey() >> shiftingBits;
00734         for (int i = 0; i < shiftingBits; i++)
00735             prefix += ((int)key.getBit(key.getLength() - dist + i) << i);
00736         OverlayKey pre(prefix);
00737         routeKey += (pre << (routeKey.getLength()-shiftingBits));
00738 
00739         findNodeExt->setRouteKey(routeKey);
00740         findNodeExt->setStep(dist - shiftingBits);
00741 
00742         KeyDistanceComparator<KeyXorMetric>* comp = NULL;
00743         comp = new KeyDistanceComparator<KeyXorMetric>(routeKey);
00744 
00745         result->setComparator(comp);
00746         rBucket[prefix]->fillVector(result);
00747         result->add(thisNode);
00748         delete comp;
00749         /*
00750         std::cout << "key: " << key.toString(2).substr(0, 8)
00751                   << " dist: " << findNodeExt->getStep()
00752                   << " rtkey: " << findNodeExt->getRouteKey().toString(2).substr(0, 8)
00753                   << " ThisNode: " << thisNode.getKey().toString(2).substr(0, 8);
00754         if (result->size() > 0) {
00755             std::cout << " next hop: " << (*result)[0].getKey().toString(2).substr(0, 8);
00756         } else {
00757             std::cout << " no next hop!";
00758         }
00759         std::cout << std::endl << std::endl;
00760         */
00761     }
00762 
00763     if ((*result)[0] == thisNode) {
00764         delete result;
00765         return (findNode(key, numRedundantNodes, numSiblings, msg));
00766     } else
00767         return result;
00768 }
00769 
00770 void Broose::finishOverlay()
00771 {
00772     // store statistics
00773     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00774     if (time < GlobalStatistics::MIN_MEASURED) return;
00775 
00776     globalStatistics->addStdDev("Broose: Number of non-routable packets/s", numFailedPackets / time);
00777     globalStatistics->addStdDev("Broose: Sent BUCKET Messages/s", bucketCount / time);
00778     globalStatistics->addStdDev("Broose: Sent BUCKET Byte/s", bucketBytesSent / time);
00779     globalStatistics->addStdDev("Broose: Bucket retries at join", bucketRetries);
00780 
00781 }
00782 
00783 void Broose::recordOverlaySentStats(BaseOverlayMessage* msg)
00784 {
00785     BaseOverlayMessage* innerMsg = msg;
00786     while (innerMsg->getType() != APPDATA &&
00787            innerMsg->getEncapsulatedMsg() != NULL) {
00788         innerMsg =
00789             static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedMsg());
00790     }
00791 
00792     switch (innerMsg->getType()) {
00793     case RPC:
00794         if ((dynamic_cast<BucketCall*>(innerMsg) != NULL) ||
00795                 (dynamic_cast<BucketResponse*>(innerMsg) != NULL)) {
00796             RECORD_STATS(bucketCount++; bucketBytesSent +=
00797                              msg->getByteLength());
00798         }
00799         break;
00800     }
00801 }
00802 
00803 void Broose::displayBucketState()
00804 {
00805     EV << "[Broose::displayBucketState() @ " << thisNode.getAddress()
00806        << " (" << thisNode.getKey().toString(16) << ")]" << endl;
00807 
00808     for (int i = 0; i < powShiftingBits; i++) {
00809         EV << "    Content of rBucket[" << i << "]: ";
00810         rBucket[i]->output();
00811     }
00812 
00813     EV << "    Content of lBucket: ";
00814     lBucket->output();
00815     EV << "    Content of bBucket: ";
00816     bBucket->output();
00817     EV << endl;
00818 }
00819 
00820 
00821 bool Broose::isSiblingFor(const NodeHandle& node,
00822                           const OverlayKey& key,
00823                           int numSiblings,
00824                           bool* err)
00825 {
00826 // TODO: node != thisNode doesn't work yet
00827     if (key.isUnspecified())
00828         error("Broose::isSiblingFor(): key is unspecified!");
00829 
00830     if (node != thisNode)
00831         error("Broose::isSiblingsFor(): "
00832               "node != thisNode is not implemented!");
00833 
00834     if (numSiblings > getMaxNumSiblings()) {
00835         opp_error("Broose::isSiblingFor(): numSiblings too big!");
00836     }
00837     // set default number of siblings to consider
00838     if (numSiblings == -1) numSiblings = getMaxNumSiblings();
00839 
00840     if (numSiblings == 0) {
00841         *err = false;
00842         return (node.getKey() == key);
00843     }
00844 
00845     if (state != READY) {
00846         *err = true;
00847         return false;
00848     }
00849 
00850     return bBucket->keyInRange(key);
00851 }
00852 
00853 void Broose::updateTooltip()
00854 {
00855     if (ev.isGUI()) {
00856         std::stringstream ttString;
00857 
00858         // show our ip and key in tooltip
00859         ttString << thisNode.getAddress() << " " << thisNode.getKey();
00860 
00861         getParentModule()->getParentModule()->getDisplayString().
00862                                   setTagArg("tt", 0, ttString.str().c_str());
00863         getParentModule()->getDisplayString().
00864                                   setTagArg("tt", 0, ttString.str().c_str());
00865         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
00866 
00867     }
00868 }
00869 
00870 bool Broose::handleRpcCall(BaseCallMessage* msg)
00871 {
00872     if (state == BSET || state == READY) {
00873         // delegate messages
00874         RPC_SWITCH_START(msg)
00875         RPC_DELEGATE(Bucket, handleBucketRequestRpc);
00876         RPC_ON_CALL(Ping) {
00877             // add pinging node to all buckets and update lastSeen of node
00878             routingAdd(msg->getSrcNode(), true);
00879             return false;
00880             break;
00881         }
00882         RPC_ON_CALL(FindNode) {
00883             // add pinging node to all buckets and update lastSeen of node
00884             routingAdd(msg->getSrcNode(), true);
00885             return false;
00886             break;
00887         }
00888         RPC_SWITCH_END()
00889         return RPC_HANDLED;
00890     } else {
00891         RPC_SWITCH_START(msg)
00892         // don't answer PING and FIND_NODE calls, if the node can't route yet
00893         RPC_ON_CALL(Ping) {
00894             delete msg;
00895             return true;
00896             break;
00897         }
00898         RPC_ON_CALL(FindNode) {
00899             delete msg;
00900             return true;
00901             break;
00902         }
00903         RPC_SWITCH_END()
00904         return RPC_HANDLED;
00905     }
00906 }
00907 
00908 void Broose::handleRpcResponse(BaseResponseMessage* msg,
00909                                const RpcState& rpcState,
00910                                simtime_t rtt)
00911 {
00912     // add sender to all buckets and update lastSeen of node
00913     routingAdd(msg->getSrcNode(), true, rtt);
00914 
00915     RPC_SWITCH_START(msg)
00916     RPC_ON_RESPONSE( Bucket ) {
00917         handleBucketResponseRpc(_BucketResponse, rpcState);
00918         EV << "[Broose::handleRpcResponse() @ " << thisNode.getAddress()
00919            << " (" << thisNode.getKey().toString(16) << ")]\n"
00920            << "    Bucket RPC Response received: id=" << rpcState.getId() << "\n"
00921            << "    msg=" << *_BucketResponse << " rtt=" << rtt
00922            << endl;
00923         break;
00924     }
00925     RPC_ON_RESPONSE(FindNode)
00926     {
00927         // add inactive nodes
00928         for (uint32_t i=0; i<_FindNodeResponse->getClosestNodesArraySize(); i++)
00929             routingAdd(_FindNodeResponse->getClosestNodes(i), false);
00930         break;
00931     }
00932     RPC_SWITCH_END( )
00933 }
00934 
00935 void Broose::handleRpcTimeout(const RpcState& rpcState)
00936 {
00937     RPC_SWITCH_START(rpcState.getCallMsg())
00938     RPC_ON_CALL(FindNode) {
00939         handleFindNodeTimeout(_FindNodeCall, rpcState.getDest(), rpcState.getDestKey());
00940         EV << "[Broose::handleRpcTimeout() @ " << thisNode.getAddress()
00941         << " (" << thisNode.getKey().toString(16) << ")]\n"
00942         << "    Find Node RPC Call timed out: id=" << rpcState.getId() << "\n"
00943         << "    msg=" << *_FindNodeCall
00944         << endl;
00945         break;
00946     }
00947     RPC_ON_CALL(Bucket) {
00948         handleBucketTimeout(_BucketCall);
00949         EV << "[Broose::handleRpcTimeout() @ " << thisNode.getAddress()
00950         << " (" << thisNode.getKey().toString(16) << ")]\n"
00951         << "    Bucket RPC Call timed out: id=" << rpcState.getId() << "\n"
00952         << "    msg=" << *_BucketCall
00953         << endl;
00954         break;
00955     }
00956     RPC_SWITCH_END()
00957 }
00958 
00959 void Broose::handleBucketRequestRpc(BucketCall* msg)
00960 {
00961     if (msg->getBucketType() == LEFT) {
00962 #if 0
00963         // TODO: dependent on the churn scenarios this may give better
00964         //       or worse results
00965         if (state == BSET) {
00966             // can't handle LBucketRequest in BSET-State
00967             delete msg;
00968             return;
00969         }
00970 #endif
00971 
00972         // return L-Bucket
00973         int size = lBucket->getSize();
00974         BucketResponse* bResponse = new BucketResponse("LBucketResponse");
00975         bResponse->setNodesArraySize(size);
00976 
00977         for (int i = 0; i < size; i++) {
00978             bResponse->setNodes(i, lBucket->get(i));
00979         }
00980 
00981         bResponse->setBitLength(BUCKETRESPONSE_L(bResponse));
00982 
00983         // only add, if the originator is already in the BSET state
00984         // in which the node already is able to do right shifting lookups
00985         // TODO: this leads to lower lookup success rates in some scenarios
00986         //       but helps to prevent deadlock situations with high churn rates
00987         if (msg->getProState() == PBSET) {
00988             routingAdd(msg->getSrcNode(), true);
00989         }
00990 
00991         sendRpcResponse(msg, bResponse);
00992     } else if (msg->getBucketType() == BROTHER) {
00993         // return B-Bucket
00994         int size = bBucket->getSize();
00995         BucketResponse* bResponse = new BucketResponse("BBucketResponse");
00996         bResponse->setNodesArraySize(size);
00997 
00998         for (int i = 0; i < size; i++) {
00999             bResponse->setNodes(i, bBucket->get(i));
01000         }
01001         bResponse->setBitLength(BUCKETRESPONSE_L(bResponse));
01002 
01003         sendRpcResponse(msg, bResponse);
01004     } else
01005         error("Broose::handleBucketRequestRpc() - Wrong Bucket Type!");
01006 }
01007 
01008 void Broose::handleBucketResponseRpc(BucketResponse* msg,
01009                                      const RpcState& rpcState)
01010 {
01011     BucketCall* call = check_and_cast<BucketCall*>(rpcState.getCallMsg());
01012 
01013     for (uint i = 0; i < msg->getNodesArraySize(); i++) {
01014         routingAdd(msg->getNodes(i), false);
01015     }
01016 
01017     if (call->getBucketType() == LEFT) {
01018         switch (state) {
01019         case RSET:
01020             if (call->getProState() == PRSET) {
01021                 receivedBBucketLookup++;
01022 
01023                 if (receivedBBucketLookup == numberBBucketLookup)
01024                     changeState(BSET);
01025             }
01026             break;
01027         case BSET:
01028             if (call->getProState() == PBSET) {
01029                 receivedLBucketLookup++;
01030 
01031                 if (receivedLBucketLookup == numberLBucketLookup)
01032                     changeState(READY);
01033             }
01034             break;
01035         default:
01036             break;
01037         }
01038     } else if (call->getBucketType() == BROTHER) {
01039         switch(state) {
01040         case INIT:
01041             if (call->getProState() == PINIT) {
01042                 receivedJoinResponse++;
01043                 if (receivedJoinResponse == powShiftingBits)
01044                     changeState(RSET);
01045             }
01046         default:
01047             break;
01048         }
01049     } else
01050         error("Broose::handleBucketRequestRpc() - unknown error.");
01051 }
01052 
01053 
01054 void Broose::handleBucketTimeout(BucketCall* msg)
01055 {
01056     if (state == READY)
01057         return;
01058     else {
01059         bucketRetries++;
01060         changeState(INIT);
01061     }
01062 }
01063 
01064 void Broose::pingResponse(PingResponse* pingResponse, cPolymorphic* context,
01065                           int rpcId, simtime_t rtt) {
01066     // if node respond reset failedResponses and add lastSeen to node
01067     routingAdd(pingResponse->getSrcNode(), true, rtt);
01068 }
01069 
01070 void Broose::routingTimeout(const BrooseHandle& handle)
01071 {
01072     for (size_t i = 0; i < bucketVector.size(); i++) {
01073         if (bucketVector[i]->getFailedResponses(handle) == numberRetries)
01074             bucketVector[i]->remove(handle);
01075         else
01076             bucketVector[i]->increaseFailedResponses(handle);
01077     }
01078 }
01079 
01080 void Broose::handleFindNodeTimeout(FindNodeCall* findNode,
01081                                    const TransportAddress& dest,
01082                                    const OverlayKey& destKey)
01083 {
01084     routingTimeout(dynamic_cast<const NodeHandle&>(dest));
01085 }
01086 
01087 void Broose::pingTimeout(PingCall* pingCall,
01088                         const TransportAddress& dest,
01089                         cPolymorphic* context, int rpcId)
01090 {
01091     routingTimeout(dynamic_cast<const NodeHandle&>(dest));
01092 }
01093 
01094 bool Broose::routingAdd(const NodeHandle& node, bool isAlive,
01095                         simtime_t rtt)
01096 {
01097     bool added = false;
01098 
01099     for (size_t i = 0; i < bucketVector.size(); i++) {
01100         added |= bucketVector[i]->add(node, isAlive, rtt);
01101     }
01102 
01103     return added;
01104 }
01105 
01106 void Broose::setLastSeen(const NodeHandle& node)
01107 {
01108     for (size_t i = 0; i < bucketVector.size(); i++) {
01109         bucketVector[i]->setLastSeen(node, simTime());
01110     }
01111 }
01112 
01113 void Broose::addNode(const NodeHandle& node)
01114 {
01115     // add node to all buckets
01116     for (size_t i = 0; i < bucketVector.size(); i++) {
01117         bucketVector[i]->add(node);
01118     }
01119 }
01120 
01121 void Broose::resetFailedResponses(const NodeHandle& node)
01122 {
01123     for (size_t i = 0; i < bucketVector.size(); i++) {
01124         bucketVector[i]->resetFailedResponses(node);
01125     }
01126 }
01127 
01128 void Broose::setRTT(const NodeHandle& node, simtime_t rtt)
01129 {
01130     for (size_t i = 0; i < bucketVector.size(); i++) {
01131         bucketVector[i]->setRTT(node, rtt);
01132     }
01133 }
01134 
01135 

Generated on Tue Sep 8 17:26:51 2009 for OverSim by  doxygen 1.5.8