00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00023 #include <omnetpp.h>
00024 #include <IPAddressResolver.h>
00025 #include <GlobalNodeListAccess.h>
00026 #include <InitStages.h>
00027 #include <NotificationBoard.h>
00028 #include <UnderlayConfigurator.h>
00029 #include <UDPControlInfo_m.h>
00030 #include <NodeHandle.h>
00031 #include <BootstrapList.h>
00032
00033 #include "I3Trigger.h"
00034 #include "I3IdentifierStack.h"
00035 #include "I3Message.h"
00036 #include "I3BaseApp.h"
00037
00038 #include <iostream>
00039 #include <sstream>
00040 #include <cfloat>
00041
00042 using namespace std;
00043
00044
00045 I3BaseApp::I3CachedServer::I3CachedServer() :
00046 lastReply(0),
00047 roundTripTime(MAXTIME)
00048 {
00049 }
00050
00051 std::ostream &operator<<(std::ostream &os, const I3BaseApp::I3CachedServer &server) {
00052 os << server.address << " rt=" << server.roundTripTime;
00053 return os;
00054 }
00055
00056
00057
00058 I3BaseApp::I3BaseApp()
00059 {
00060 }
00061
00062 I3BaseApp::~I3BaseApp()
00063 {
00064 }
00065
00066 int I3BaseApp::numInitStages() const
00067 {
00068 return MAX_STAGE_APP + 1;
00069 }
00070
00071 void I3BaseApp::initialize(int stage)
00072 {
00073 if (stage != MIN_STAGE_APP) return;
00074
00075 nodeIPAddress = IPAddressResolver().addressOf(getParentModule());
00076
00077 bindToPort(par("clientPort"));
00078
00079
00080
00081 getDisplayString().setTagArg("i", 0, "i3c");
00082 getParentModule()->getDisplayString().removeTag("i2");
00083
00084 if (int(par("bootstrapTime")) >= int(par("initTime"))) {
00085 opp_error("Parameter bootstrapTime must be smaller than initTime");
00086 }
00087
00088 bootstrapTimer = new cMessage();
00089 scheduleAt(simTime() + int(par("bootstrapTime")), bootstrapTimer);
00090
00091 initializeTimer = new cMessage();
00092 scheduleAt(simTime() + int(par("initTime")), initializeTimer);
00093
00094 numSent = 0;
00095 sentBytes = 0;
00096 numReceived = 0;
00097 receivedBytes = 0;
00098 numIsolations = 0;
00099 mobilityInStages = false;
00100
00101 WATCH(nodeIPAddress);
00102 WATCH(numSent);
00103 WATCH(sentBytes);
00104 WATCH(numReceived);
00105 WATCH(receivedBytes);
00106 WATCH(numIsolations);
00107
00108
00109 WATCH_SET(insertedTriggers);
00110 WATCH(gateway);
00111 WATCH_MAP(samplingCache);
00112 WATCH_MAP(identifierCache);
00113
00114 initializeApp(stage);
00115 }
00116
00117 void I3BaseApp::initializeApp(int stage)
00118 {
00119 }
00120
00121 void I3BaseApp::bootstrapI3()
00122 {
00123 I3IPAddress myAddress(nodeIPAddress, par("clientPort"));
00124
00125
00126 const NodeHandle handle = GlobalNodeListAccess().get()->getBootstrapNode();
00127 gateway.address = I3IPAddress(handle.getAddress(), par("serverPort"));
00128
00129 int cacheSize = par("cacheSize");
00130 for (int i = 0; i < cacheSize; i++) {
00131 I3Identifier id;
00132
00133 id.createRandomKey();
00134
00135 ostringstream os;
00136 os << myAddress << " sample" << i;
00137 id.setName(os.str());
00138
00139 samplingCache[id] = I3CachedServer();
00140
00141 insertTrigger(id, false);
00142 }
00143
00144 refreshTriggersTimer = new cMessage();
00145 refreshTriggersTime = par("triggerRefreshTime");
00146 scheduleAt(simTime() + truncnormal(refreshTriggersTime, refreshTriggersTime / 10),
00147 refreshTriggersTimer);
00148
00149 refreshSamplesTimer = new cMessage();
00150 refreshSamplesTime = par("sampleRefreshTime");
00151 scheduleAt(simTime() + truncnormal(refreshSamplesTime, refreshSamplesTime / 10),
00152 refreshSamplesTimer);
00153 }
00154
00155 void I3BaseApp::initializeI3()
00156 {
00157
00158 }
00159
00160 void I3BaseApp::handleMessage(cMessage *msg)
00161 {
00162 if (msg->isSelfMessage()) {
00163 if (msg == bootstrapTimer) {
00164 bootstrapI3();
00165 delete msg;
00166 bootstrapTimer = 0;
00167 } else if (msg == initializeTimer) {
00168 initializeI3();
00169 delete msg;
00170 initializeTimer = 0;
00171 } else if (msg == refreshTriggersTimer) {
00172 refreshTriggers();
00173 scheduleAt(simTime() + truncnormal(refreshTriggersTime, refreshTriggersTime / 10),
00174 refreshTriggersTimer);
00175 } else if (msg == refreshSamplesTimer) {
00176 refreshSamples();
00177 scheduleAt(simTime() + truncnormal(refreshSamplesTime, refreshSamplesTime / 10),
00178 refreshSamplesTimer);
00179 } else {
00180 handleTimerEvent(msg);
00181 }
00182 } else if (msg->arrivedOn("udpIn")) {
00183 handleUDPMessage(msg);
00184 } else {
00185 delete msg;
00186 }
00187 }
00188
00189 void I3BaseApp::deliver(I3Trigger &matchingTrigger, I3IdentifierStack &stack, cPacket *msg)
00190 {
00191 delete msg;
00192 }
00193
00194 void I3BaseApp::handleTimerEvent(cMessage *msg)
00195 {
00196 delete msg;
00197 }
00198
00199 void I3BaseApp::handleUDPMessage(cMessage *msg)
00200 {
00201 I3Message *i3msg;
00202
00203 i3msg = dynamic_cast<I3Message*>(msg);
00204 if (i3msg) {
00205 switch (i3msg->getType()) {
00206 case SEND_PACKET:
00207 {
00208 I3SendPacketMessage *smsg;
00209
00210 smsg = check_and_cast<I3SendPacketMessage*>(msg);
00211 numReceived++;
00212 receivedBytes += smsg->getByteLength();
00213
00214
00215 cPacket *newMessage = smsg->decapsulate();
00216 deliver(smsg->getMatchedTrigger(), smsg->getIdentifierStack(), newMessage);
00217
00218 break;
00219 }
00220 case QUERY_REPLY:
00221 {
00222 I3QueryReplyMessage *pmsg;
00223 pmsg = check_and_cast<I3QueryReplyMessage*>(msg);
00224 I3Identifier &id = pmsg->getIdentifier();
00225
00226 identifierCache[id].address = pmsg->getSource();
00227 identifierCache[id].lastReply = simTime();
00228 identifierCache[id].roundTripTime = simTime() - pmsg->getSendingTime();
00229
00230 if (samplingCache.count(id) != 0) {
00231 samplingCache[id] = identifierCache[id];
00232 }
00233 break;
00234 }
00235 default:
00236
00237 break;
00238 }
00239 }
00240 delete msg;
00241 }
00242
00243 void I3BaseApp::sendToI3(I3Message *msg)
00244 {
00245 sendThroughUDP(msg, gateway.address);
00246 }
00247
00248 void I3BaseApp::sendThroughUDP(cMessage *msg, const I3IPAddress &add)
00249 {
00250 msg->removeControlInfo();
00251 msg->setKind(UDP_C_DATA);
00252
00253 UDPControlInfo* udpControlInfo = new UDPControlInfo();
00254 udpControlInfo->setSrcAddr(nodeIPAddress);
00255 udpControlInfo->setSrcPort(par("clientPort"));
00256
00257 udpControlInfo->setDestAddr(add.getAddress());
00258 udpControlInfo->setDestPort(add.getPort());
00259
00260 msg->setControlInfo(udpControlInfo);
00261 send(msg, "udpOut");
00262 }
00263
00264 void I3BaseApp::refreshTriggers()
00265 {
00266 I3IPAddress myAddress(nodeIPAddress, par("clientPort"));
00267 map<I3Identifier, I3CachedServer>::iterator mit;
00268
00269
00270
00271 int serverTimeout = par("serverTimeout");
00272 gateway.roundTripTime = serverTimeout;
00273 I3Identifier gatewayId;
00274 for (mit = samplingCache.begin(); mit != samplingCache.end(); mit++) {
00275 if (gateway.roundTripTime > mit->second.roundTripTime) {
00276 gatewayId = mit->first;
00277 gateway = mit->second;
00278 }
00279 }
00280
00281
00282 if (simTime() - gateway.lastReply >= serverTimeout) {
00283
00284
00285
00286 int random = intrand(samplingCache.size()), i;
00287
00288 EV << "I3BaseApp::refreshTriggers()]\n"
00289 << " Gateway timeout at " << nodeIPAddress
00290 << ", time " << simTime()
00291 << "; expired gateway is " << gateway << "(" << gatewayId << ") "
00292 << " with last reply at " << gateway.lastReply
00293 << endl;
00294
00295 for (i = 0, mit = samplingCache.begin(); i < random; i++, mit++);
00296 gateway = mit->second;
00297 EV << "I3BaseApp::refreshTriggers()]\n"
00298 << " New gateway for " << nodeIPAddress << " is " << gateway
00299 << endl;
00300
00301 if (gateway.roundTripTime > 2 * serverTimeout) {
00302 EV << "I3BaseApp::refreshTriggers()]\n"
00303 << " New gateway's (" << gateway << ") rtt for " << nodeIPAddress
00304 << " too high... marking as isolated!"
00305 << endl;
00306 numIsolations++;
00307 const NodeHandle handle = GlobalNodeListAccess().get()->getBootstrapNode();
00308 gateway.address = I3IPAddress(handle.getAddress(), par("serverPort"));
00309 }
00310 }
00311
00312
00313 insertTrigger(gatewayId, false);
00314
00315
00316
00317 set<I3Trigger>::iterator it;
00318 for (it = insertedTriggers.begin(); it != insertedTriggers.end(); it++) {
00319 insertTrigger(*it, false);
00320 }
00321
00322
00323 int idStoreTime = par("idStoreTime");
00324 for (mit = identifierCache.begin(); mit != identifierCache.end(); mit++) {
00325 if (mit->second.lastReply - simTime() > idStoreTime) {
00326 identifierCache.erase(mit);
00327 }
00328 }
00329
00330 }
00331
00332 void I3BaseApp::refreshSamples() {
00333 map<I3Identifier, I3CachedServer>::iterator mit;
00334
00335 EV << "I3BaseApp::refreshSamples()]\n"
00336 << " Refresh samples!"
00337 << endl;
00338
00339 for (mit = samplingCache.begin(); mit != samplingCache.end(); mit++) {
00340 insertTrigger(mit->first, false);
00341 }
00342 }
00343
00344 I3Identifier I3BaseApp::retrieveClosestIdentifier()
00345 {
00346 simtime_t time;
00347 I3Identifier id;
00348 map<I3Identifier, I3CachedServer>::iterator mit;
00349 I3IPAddress myAddress(nodeIPAddress, par("clientPort"));
00350
00351 time = MAXTIME;
00352 for (mit = samplingCache.begin(); mit != samplingCache.end(); mit++) {
00353 if (time > mit->second.roundTripTime) {
00354 time = mit->second.roundTripTime;
00355 id = mit->first;
00356 }
00357 }
00358 samplingCache.erase(id);
00359
00360 I3Identifier rid;
00361 rid.createRandomKey();
00362
00363 ostringstream os;
00364 os << myAddress << " sample";
00365 rid.setName(os.str());
00366
00367 samplingCache[rid] = I3CachedServer();
00368 insertTrigger(rid, false);
00369
00370 return id;
00371 }
00372
00373 void I3BaseApp::sendPacket(const I3Identifier &id, cPacket *msg, bool useHint)
00374 {
00375 I3IdentifierStack stack;
00376
00377 stack.push(id);
00378 sendPacket(stack, msg, useHint);
00379 }
00380
00381 void I3BaseApp::sendPacket(const I3IdentifierStack &stack, cPacket *msg, bool useHint)
00382 {
00383 I3SendPacketMessage *smsg;
00384
00385 smsg = new I3SendPacketMessage();
00386 smsg->setBitLength(SEND_PACKET_L(smsg));
00387 smsg->encapsulate(msg);
00388 smsg->setIdentifierStack(stack);
00389
00390 smsg->setSendReply(useHint);
00391 if (useHint) {
00392 I3IPAddress add(nodeIPAddress, par("clientPort"));
00393 smsg->setSource(add);
00394 }
00395
00396 numSent++;
00397 sentBytes += smsg->getByteLength();
00398
00399 I3SubIdentifier subid = stack.peek();
00400 if (subid.getType() == I3SubIdentifier::IPAddress) {
00401 smsg->getIdentifierStack().pop();
00402 sendThroughUDP(smsg, subid.getIPAddress());
00403 } else {
00404
00405 I3IPAddress address = (useHint && identifierCache.count(subid.getIdentifier()) != 0) ?
00406 identifierCache[subid.getIdentifier()].address :
00407 gateway.address;
00408 sendThroughUDP(smsg, address);
00409 }
00410 }
00411
00412 void I3BaseApp::insertTrigger(const I3Identifier &identifier, bool store)
00413 {
00414 I3Trigger trigger;
00415 I3IPAddress add(nodeIPAddress, par("clientPort"));;
00416
00417 trigger.getIdentifierStack().push(add);
00418 trigger.setIdentifier(identifier);
00419 insertTrigger(trigger, store);
00420 }
00421
00422 void I3BaseApp::insertTrigger(const I3Identifier &identifier, const I3IdentifierStack &stack, bool store)
00423 {
00424 I3Trigger trigger;
00425
00426 trigger.setIdentifier(identifier);
00427 trigger.getIdentifierStack() = stack;
00428 insertTrigger(trigger, store);
00429 }
00430
00431 void I3BaseApp::insertTrigger(const I3Trigger &t, bool store) {
00432
00433 if (store) {
00434 if (insertedTriggers.count(t) != 0) return;
00435 insertedTriggers.insert(t);
00436 }
00437
00438 I3InsertTriggerMessage *msg = new I3InsertTriggerMessage();
00439 I3IPAddress myAddress(nodeIPAddress, par("clientPort"));
00440
00441 msg->setTrigger(t);
00442 msg->setSendReply(true);
00443 msg->setSource(myAddress);
00444 msg->setBitLength(INSERT_TRIGGER_L(msg));
00445
00446 sendThroughUDP(msg, gateway.address);
00447 }
00448
00449 void I3BaseApp::removeTrigger(const I3Identifier &identifier)
00450 {
00451 I3Trigger dummy;
00452 dummy.setIdentifier(identifier);
00453
00454 set<I3Trigger>::iterator it = insertedTriggers.lower_bound(dummy);
00455 if (it == insertedTriggers.end()) return;
00456
00457 for (; it != insertedTriggers.end() && it->getIdentifier() == identifier; it++) {
00458 removeTrigger(*it);
00459 }
00460 }
00461
00462 void I3BaseApp::removeTrigger(const I3Trigger &t)
00463 {
00464 I3RemoveTriggerMessage *msg = new I3RemoveTriggerMessage();
00465 msg->setTrigger(t);
00466 msg->setBitLength(REMOVE_TRIGGER_L(msg));
00467 sendThroughUDP(msg, gateway.address);
00468
00469 insertedTriggers.erase(t);
00470 }
00471
00472 set<I3Trigger> &I3BaseApp::getInsertedTriggers()
00473 {
00474 return insertedTriggers;
00475 }
00476
00477 void I3BaseApp::receiveChangeNotification (int category, const cPolymorphic *details)
00478 {
00479 Enter_Method_Silent();
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 }
00546
00547 void I3BaseApp::doMobilityEvent(I3MobilityStage category)
00548 {
00549 }