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