I3.cc

Go to the documentation of this file.
00001 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00002 //
00003 // This program is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU General Public License
00005 // as published by the Free Software Foundation; either version 2
00006 // of the License, or (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00016 //
00017 
00023 #include <UDPAppBase.h>
00024 #include <UDPControlInfo_m.h>
00025 #include "UDPSocket.h"
00026 #include "UDPControlInfo_m.h"
00027 
00028 #include <IPAddressResolver.h>
00029 #include <CommonMessages_m.h>
00030 #include <GlobalNodeListAccess.h>
00031 #include <UnderlayConfiguratorAccess.h>
00032 
00033 #include <omnetpp.h>
00034 #include <OverlayKey.h>
00035 #include "SHA1.h"
00036 
00037 #include "TriggerTable.h"
00038 #include "I3Identifier.h"
00039 #include "I3IPAddress.h"
00040 #include "I3SubIdentifier.h"
00041 #include "I3IdentifierStack.h"
00042 #include "I3Trigger.h"
00043 #include "I3Message_m.h"
00044 #include "I3Message.h"
00045 #include "I3.h"
00046 
00047 using namespace std;
00048 
00049 std::ostream& operator<<(std::ostream& os, const I3TriggerSet &t)
00050 {
00051     os << endl;
00052 
00053     I3TriggerSet::iterator it;
00054     for (it = t.begin(); it != t.end(); it++) {
00055         os << *it << " in " << it->getInsertionTime() << "(" <<
00056         (simTime() - it->getInsertionTime()) << ")" << endl;
00057     }
00058     return os;
00059 }
00060 
00061 Define_Module(I3);
00062 
00063 const I3Identifier *I3::findClosestMatch(const I3Identifier &t) const
00064 {
00065     int prevDist = 0, nextDist = 0;
00066 
00067 
00068     if (triggerTable.size() == 0) return 0;
00069 
00070     /* find the closest identifier to t */
00071     /* if no match exists, it gets the next identifier with a bigger key */
00072     I3TriggerTable::const_iterator it = triggerTable.lower_bound(t);
00073 
00074     if (it == triggerTable.end()) {
00075         it--;               // if at the end, check last
00076     }
00077 
00078     if (it->first == t) return &it->first; // if we found an exact match, no need to bother
00079 
00080     if (it != triggerTable.begin()) { // if no smaller keys, begin() is the candidate itself
00081 
00082         /* no exact match, check which is closer: */
00083         /* either where the iterator points to (the next biggest) or the previous one. */
00084         /* see I3Identifier::distanceTo for distance definition */
00085 
00086         nextDist = it->first.distanceTo(t);
00087         it--;
00088         prevDist = it->first.distanceTo(t);
00089 
00090         // if the next one is closest, put iterator back in place
00091         if (nextDist < prevDist) {
00092             it++;
00093         }
00094     }
00095 
00096     /* now check if they match in the I3 sense (first prefixLength bits) */
00097     return (it->first.isMatch(t)) ? &it->first : 0;
00098 }
00099 
00100 void I3::insertTrigger(I3Trigger &t)
00101 {
00102 
00103     if (t.getIdentifierStack().size() == 0) {
00104         /* don't bother */
00105         cout << "Warning: Got trigger " << t << " with size 0 in " << thisNode.getAddress()<< endl;
00106         return;
00107     }
00108 
00109     t.setInsertionTime(simTime());
00110 
00111     /* insert packet in triggerTable; */
00112     /* if it was already there, remove and insert updated copy */
00113 
00114     triggerTable[t.getIdentifier()].erase(t);
00115     triggerTable[t.getIdentifier()].insert(t);
00116 
00117     updateTriggerTableString();
00118 }
00119 
00120 void I3::removeTrigger(I3Trigger &t)
00121 {
00122 
00123     //cout << "Removing trigger at " << getId() << endl;
00124     //getParentModule()->getParentModule()->bubble("Removing trigger");
00125 
00126     if (triggerTable.count(t.getIdentifier()) == 0) return;
00127 
00128     set<I3Trigger> &s = triggerTable[t.getIdentifier()];
00129 
00130     s.erase(t);
00131 
00132     if (s.size() == 0) triggerTable.erase(t.getIdentifier());
00133 
00134     updateTriggerTableString();
00135 }
00136 
00137 void I3::sendToNode(I3SendPacketMessage *imsg)
00138 {
00139     I3IPAddress address;
00140     /* re-route message to a client node */
00141     address = imsg->getIdentifierStack().peek().getIPAddress();
00142     imsg->getIdentifierStack().pop(); // pop ip address
00143     sendMessageToUDP(address, imsg);
00144 }
00145 
00146 void I3::sendPacket(I3SendPacketMessage *msg)
00147 {
00148 
00149     I3IdentifierStack &idStack = msg->getIdentifierStack();
00150 
00151     if (idStack.size() == 0) {
00152         /* no identifiers left! drop packet */
00153         /* shouldn't happen (how'd it get here anyway?) */
00154         numDroppedPackets++;
00155         byteDroppedPackets += msg->getBitLength();
00156         delete msg;
00157         return;
00158     }
00159 
00160     I3SubIdentifier id = idStack.peek();
00161 
00162     if (id.getType() == I3SubIdentifier::IPAddress) {
00163         /* shouldn't happen (how'd they find us anyway?) but just in case */
00164         sendToNode(msg);
00165     } else {
00166 
00167         /* if we were asked to reply, send it now */
00168         if (msg->getSendReply()) {
00169             sendQueryReply(id.getIdentifier(), msg->getSource());
00170         }
00171 
00172         const I3Identifier *i3id = findClosestMatch(id.getIdentifier());
00173 
00174         /* eliminate top of the stack */
00175         idStack.pop();
00176 
00177         if (!i3id) {
00178             /* no matching ids found in this server, re-route to next id */
00179             if (idStack.size() == 0) {
00180                 /* no identifiers left! drop packet */
00181                 numDroppedPackets++;
00182                 byteDroppedPackets += msg->getBitLength();
00183                 cout << "Dropped packet at" << thisNode.getAddress()<< " to unknown id " << id.getIdentifier() << endl;
00184                 delete msg;
00185                 return;
00186             } else {
00187                 msg->setBitLength(SEND_PACKET_L(msg)); /* stack size changed, recalculate */
00188                 if (idStack.peek().getType() == I3SubIdentifier::IPAddress) {
00189                     msg->getMatchedTrigger().clear(); // not trigger, but direct IP match
00190                     sendToNode(msg);
00191                 } else {
00192                     OverlayKey key = idStack.peek().getIdentifier().asOverlayKey();
00193                     callRoute(key, msg);
00194                 }
00195             }
00196 
00197         } else {
00198             /* some id found, send to all friends */
00199             set<I3Trigger> &s = triggerTable[*i3id];
00200             set<I3Trigger>::iterator it;
00201 
00202             for (it = s.begin(); it != s.end(); it++) {
00203                 I3SendPacketMessage *newMsg;
00204                 cPacket *dupMsg;
00205 
00206                 newMsg = new I3SendPacketMessage();
00207                 newMsg->setIdentifierStack(idStack); /* create copy */
00208                 newMsg->getIdentifierStack().push(it->getIdentifierStack()); /* append our stuff to the top of the stack */
00209                 dupMsg = check_and_cast<cPacket*>(msg->getEncapsulatedPacket()->dup()); /* dup msg */
00210                 newMsg->setBitLength(SEND_PACKET_L(newMsg)); /* stack size changed, recalculate */
00211                 newMsg->encapsulate(dupMsg);
00212 
00213                 I3SubIdentifier &top = newMsg->getIdentifierStack().peek();
00214 
00215                 if (top.getType() == I3SubIdentifier::IPAddress) {
00216                     newMsg->setMatchedTrigger(*it);
00217                     sendToNode(newMsg);
00218                 } else {
00219                     OverlayKey key = top.getIdentifier().asOverlayKey();
00220                     callRoute(key, newMsg);
00221                 }
00222             }
00223 
00224             /* copies sent, erase original */
00225             delete msg;
00226 
00227         }
00228     }
00229 }
00230 
00231 void I3::forward(OverlayKey *key, cPacket **msg, NodeHandle *hint)
00232 {
00233     numForwardedPackets++;
00234     numForwardedBytes += (*msg)->getByteLength();
00235 
00236     BaseApp::forward(key, msg, hint);
00237 }
00238 
00239 
00240 void I3::handleUDPMessage(cMessage *msg)
00241 {
00242     I3Message *i3msg;
00243 
00244     i3msg = dynamic_cast<I3Message*>(msg);
00245 
00246     if (!i3msg) {
00247         delete msg;
00248         return;
00249     }
00250 
00251     OverlayKey key;
00252 
00253     msg->removeControlInfo();
00254     switch (i3msg->getType()) {
00255     case INSERT_TRIGGER:
00256         I3InsertTriggerMessage *imsg;
00257 
00258         imsg = check_and_cast<I3InsertTriggerMessage*>(i3msg);
00259         key = imsg->getTrigger().getIdentifier().asOverlayKey();
00260         callRoute(key, imsg);
00261 
00262         /*            if ((imsg->getSource().address.d[0] & 0xff) == 56) {
00263                     cout << "UDP Server " << thisNode.getAddress()<< " trigger " << imsg->getTrigger() << " key " << key << endl;
00264             }*/
00265 
00266         break;
00267     case REMOVE_TRIGGER:
00268         I3RemoveTriggerMessage *rmsg;
00269 
00270         rmsg = check_and_cast<I3RemoveTriggerMessage*>(i3msg);
00271         key = rmsg->getTrigger().getIdentifier().asOverlayKey();
00272         callRoute(key, rmsg);
00273 
00274         break;
00275     case SEND_PACKET:
00276     {
00277         I3SendPacketMessage *smsg;
00278 
00279         smsg = check_and_cast<I3SendPacketMessage*>(i3msg);
00280         if (smsg->getIdentifierStack().size() == 0) {
00281             /* got an empty identifier stack - nothing to do */
00282             delete msg;
00283             return;
00284         }
00285         I3SubIdentifier &subId = smsg->getIdentifierStack().peek();
00286         if (subId.getType() == I3SubIdentifier::IPAddress) {
00287             /* why didn't they send it directly?! */
00288             sendToNode(smsg);
00289         } else {
00290             key = subId.getIdentifier().asOverlayKey();
00291             callRoute(key, smsg);
00292         }
00293         break;
00294     }
00295     default:
00296         /* should't happen */
00297         delete msg;
00298         break;
00299     }
00300 }
00301 
00302 void I3::sendQueryReply(const I3Identifier &id, const I3IPAddress &add) {
00303     I3QueryReplyMessage *pmsg;
00304     I3IPAddress myAddress(thisNode.getAddress(), par("serverPort"));
00305 
00306     pmsg = new I3QueryReplyMessage();
00307     pmsg->setSource(myAddress);
00308     pmsg->setSendingTime(simTime());
00309     pmsg->setIdentifier(id);
00310     pmsg->setBitLength(QUERY_REPLY_L(pmsg));
00311     sendMessageToUDP(add, pmsg);
00312 }
00313 
00314 void I3::deliver(OverlayKey& key, cMessage* msg)
00315 {
00316     I3Message *i3msg;
00317 
00318     i3msg = dynamic_cast<I3Message*>(msg);
00319     if (!i3msg) {
00320         cout << "Delivered non I3 Message!" << endl;
00321         delete msg;
00322         return;
00323     }
00324 
00325     switch (i3msg->getType()) {
00326     case INSERT_TRIGGER:
00327         I3InsertTriggerMessage *imsg;
00328 
00329         imsg = check_and_cast<I3InsertTriggerMessage*>(i3msg);
00330         insertTrigger(imsg->getTrigger());
00331 
00332         if (imsg->getSendReply()) {
00333             sendQueryReply(imsg->getTrigger().getIdentifier(), imsg->getSource());
00334         }
00335 
00336         delete msg;
00337         break;
00338     case REMOVE_TRIGGER:
00339         I3RemoveTriggerMessage *rmsg;
00340 
00341         rmsg = check_and_cast<I3RemoveTriggerMessage*>(i3msg);
00342         removeTrigger(rmsg->getTrigger());
00343         delete msg;
00344         break;
00345     case SEND_PACKET:
00346         I3SendPacketMessage *smsg;
00347 
00348         smsg = check_and_cast<I3SendPacketMessage*>(i3msg);
00349         sendPacket(smsg);
00350 
00351         break;
00352     default:
00353         delete msg;
00354         break;
00355     }
00356 }
00357 
00358 int I3::numInitStages() const
00359 {
00360     return MIN_STAGE_APP + 1;
00361 }
00362 
00363 void I3::initializeApp(int stage)
00364 {
00365     if (stage != MIN_STAGE_APP)
00366         return;
00367 
00368     numDroppedPackets = 0;
00369     WATCH(numDroppedPackets);
00370     byteDroppedPackets = 0;
00371     WATCH(byteDroppedPackets);
00372 
00373     numForwardedPackets = 0;
00374     numForwardedBytes = 0;
00375 
00376     WATCH(numForwardedPackets);
00377     WATCH(numForwardedBytes);
00378 
00379     triggerTimeToLive = par("triggerTimeToLive");
00380     WATCH(triggerTimeToLive);
00381 
00382     expirationTimer = new cMessage("expiration timer");
00383     scheduleAt(simTime() + triggerTimeToLive, expirationTimer);
00384 
00385     getDisplayString() = "i=i3";
00386 
00387     thisNode.setPort(par("serverPort"));
00388     bindToPort(thisNode.getPort());
00389 
00390 }
00391 
00392 void I3::handleTimerEvent(cMessage* msg)
00393 {
00394     bool updateString = false;
00395 
00396     if (msg == expirationTimer) {
00397         scheduleAt(simTime() + triggerTimeToLive, expirationTimer);
00398 
00399         for (I3TriggerTable::iterator it = triggerTable.begin(); it != triggerTable.end(); it++) {
00400             set<I3Trigger> &triggerSet = it->second;
00401             for (set<I3Trigger>::const_iterator sit = triggerSet.begin(); sit != triggerSet.end(); sit++) {
00402                 //cout << "Trigger " << *sit << " has
00403                 if (simTime() - sit->getInsertionTime() > triggerTimeToLive) {
00404                     //if ((bool)par("debugOutput")) {
00405                     //  cout << "Erasing trigger " << *sit << " in " <<
00406                     //          thisNode.getAddress()<< ", insertion time is " << sit->getInsertionTime()<< endl;
00407                     //}
00408                     triggerSet.erase(sit);
00409                     updateString = true;
00410                 }
00411             }
00412             if (it->second.size() == 0) {
00413                 triggerTable.erase(it);
00414             }
00415         }
00416         if (updateString) updateTriggerTableString();
00417     } else delete msg;
00418 }
00419 
00420 void I3::updateTriggerTableString()
00421 {
00422     TriggerTable *table = check_and_cast<TriggerTable*>(getParentModule()->getSubmodule("triggerTable"));
00423     table->updateDisplayString();
00424 }
00425 
00426 I3TriggerTable &I3::getTriggerTable()
00427 {
00428     return triggerTable;
00429 }
00430 
00431 void I3::finish()
00432 {
00433     recordScalar("I3 Packets dropped", numDroppedPackets);
00434     recordScalar("I3 Bytes dropped", byteDroppedPackets);
00435 }
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3