#include <I3.h>
Public Member Functions | |
I3TriggerTable & | getTriggerTable () |
Returns the table of inserted triggers. | |
const I3Identifier * | findClosestMatch (const I3Identifier &t) const |
Finds the closest match to t from the stored trigger identifiers. | |
void | insertTrigger (I3Trigger &t) |
Inserts a trigger into I3. | |
void | removeTrigger (I3Trigger &t) |
Removes a trigger from I3. | |
void | sendPacket (I3SendPacketMessage *msg) |
Sends a packet through I3. | |
void | sendToNode (I3SendPacketMessage *imsg) |
Sends packet to matching IP address (used by sendPacket). | |
Protected Member Functions | |
int | numInitStages () const |
Returns number of required init stages. | |
virtual void | initializeApp (int stage) |
Actual initialization function. | |
virtual void | deliver (OverlayKey &key, cMessage *msg) |
Delivers a packet from the overlay. | |
virtual void | handleUDPMessage (cMessage *msg) |
Handles a message from UDP. | |
virtual void | handleTimerEvent (cMessage *msg) |
Handles timers. | |
void | sendQueryReply (const I3Identifier &id, const I3IPAddress &add) |
Replies to a query of which server is responsible for the given identifier (this server). | |
virtual void | forward (OverlayKey *key, cMessage **msg, NodeHandle *nextHopNode) |
Common API function: handles messages from overlay to be forwarded. | |
void | updateTriggerTableString () |
Updates TriggerTable's module display string. | |
virtual void | finish () |
collects statistical data | |
Protected Attributes | |
int | numDroppedPackets |
Number of dropped packets. | |
int | byteDroppedPackets |
int | numForwardedPackets |
int | numForwardedBytes |
int | triggerTimeToLive |
Time before inserted triggers expire. | |
I3TriggerTable | triggerTable |
Table containing inserted triggers. | |
cMessage * | expirationTimer |
Timer to check for trigger expiration. |
int I3::numInitStages | ( | ) | const [protected] |
Returns number of required init stages.
Reimplemented from BaseApp.
00356 { 00357 return MIN_STAGE_APP + 1; 00358 }
void I3::initializeApp | ( | int | stage | ) | [protected, virtual] |
Actual initialization function.
stage | Actual stage |
Reimplemented from BaseApp.
Reimplemented in I3TRTServer.
Referenced by I3TRTServer::initializeApp().
00361 { 00362 if (stage != MIN_STAGE_APP) 00363 return; 00364 00365 numDroppedPackets = 0; 00366 WATCH(numDroppedPackets); 00367 byteDroppedPackets = 0; 00368 WATCH(byteDroppedPackets); 00369 00370 numForwardedPackets = 0; 00371 numForwardedBytes = 0; 00372 00373 WATCH(numForwardedPackets); 00374 WATCH(numForwardedBytes); 00375 00376 triggerTimeToLive = par("triggerTimeToLive"); 00377 WATCH(triggerTimeToLive); 00378 00379 expirationTimer = new cMessage("expiration timer"); 00380 scheduleAt(simulation.simTime() + triggerTimeToLive, expirationTimer); 00381 00382 displayString() = "i=i3"; 00383 00384 thisNode.port = par("serverPort"); 00385 bindToPort(thisNode.port); 00386 00387 }
void I3::deliver | ( | OverlayKey & | key, | |
cMessage * | msg | |||
) | [protected, virtual] |
Delivers a packet from the overlay.
key | Key from the overlay | |
msg | Message to deliver |
Reimplemented from BaseApp.
Reimplemented in I3TRTServer.
Referenced by I3TRTServer::deliver().
00312 { 00313 I3Message *i3msg; 00314 00315 i3msg = dynamic_cast<I3Message*>(msg); 00316 if (!i3msg) { 00317 cout << "Delivered non I3 Message!" << endl; 00318 delete msg; 00319 return; 00320 } 00321 00322 switch (i3msg->getType()) { 00323 case INSERT_TRIGGER: 00324 I3InsertTriggerMessage *imsg; 00325 00326 imsg = check_and_cast<I3InsertTriggerMessage*>(i3msg); 00327 insertTrigger(imsg->getTrigger()); 00328 00329 if (imsg->getSendReply()) { 00330 sendQueryReply(imsg->getTrigger().getIdentifier(), imsg->getSource()); 00331 } 00332 00333 delete msg; 00334 break; 00335 case REMOVE_TRIGGER: 00336 I3RemoveTriggerMessage *rmsg; 00337 00338 rmsg = check_and_cast<I3RemoveTriggerMessage*>(i3msg); 00339 removeTrigger(rmsg->getTrigger()); 00340 delete msg; 00341 break; 00342 case SEND_PACKET: 00343 I3SendPacketMessage *smsg; 00344 00345 smsg = check_and_cast<I3SendPacketMessage*>(i3msg); 00346 sendPacket(smsg); 00347 00348 break; 00349 default: 00350 delete msg; 00351 break; 00352 } 00353 }
void I3::handleUDPMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Handles a message from UDP.
msg | Incoming message |
Reimplemented from BaseApp.
00238 { 00239 I3Message *i3msg; 00240 00241 i3msg = dynamic_cast<I3Message*>(msg); 00242 00243 if (!i3msg) { 00244 delete msg; 00245 return; 00246 } 00247 00248 OverlayKey key; 00249 00250 msg->removeControlInfo(); 00251 switch (i3msg->getType()) { 00252 case INSERT_TRIGGER: 00253 I3InsertTriggerMessage *imsg; 00254 00255 imsg = check_and_cast<I3InsertTriggerMessage*>(i3msg); 00256 key = imsg->getTrigger().getIdentifier().asOverlayKey(); 00257 callRoute(key, imsg); 00258 00259 /* if ((imsg->getSource().address.d[0] & 0xff) == 56) { 00260 cout << "UDP Server " << thisNode.ip << " trigger " << imsg->getTrigger() << " key " << key << endl; 00261 }*/ 00262 00263 break; 00264 case REMOVE_TRIGGER: 00265 I3RemoveTriggerMessage *rmsg; 00266 00267 rmsg = check_and_cast<I3RemoveTriggerMessage*>(i3msg); 00268 key = rmsg->getTrigger().getIdentifier().asOverlayKey(); 00269 callRoute(key, rmsg); 00270 00271 break; 00272 case SEND_PACKET: 00273 { 00274 I3SendPacketMessage *smsg; 00275 00276 smsg = check_and_cast<I3SendPacketMessage*>(i3msg); 00277 if (smsg->getIdentifierStack().size() == 0) { 00278 /* got an empty identifier stack - nothing to do */ 00279 delete msg; 00280 return; 00281 } 00282 I3SubIdentifier &subId = smsg->getIdentifierStack().peek(); 00283 if (subId.getType() == I3SubIdentifier::IPAddress) { 00284 /* why didn't they send it directly?! */ 00285 sendToNode(smsg); 00286 } else { 00287 key = subId.getIdentifier().asOverlayKey(); 00288 callRoute(key, smsg); 00289 } 00290 break; 00291 } 00292 default: 00293 /* should't happen */ 00294 delete msg; 00295 break; 00296 } 00297 }
void I3::handleTimerEvent | ( | cMessage * | msg | ) | [protected, virtual] |
Handles timers.
msg | Timer |
Reimplemented from BaseApp.
00390 { 00391 bool updateString = false; 00392 00393 if (msg == expirationTimer) { 00394 scheduleAt(simulation.simTime() + triggerTimeToLive, expirationTimer); 00395 00396 for (I3TriggerTable::iterator it = triggerTable.begin(); it != triggerTable.end(); it++) { 00397 set<I3Trigger> &triggerSet = it->second; 00398 for (set<I3Trigger>::const_iterator sit = triggerSet.begin(); sit != triggerSet.end(); sit++) { 00399 //cout << "Trigger " << *sit << " has 00400 if (simulation.simTime() - sit->getInsertionTime() > triggerTimeToLive) { 00401 //if ((bool)par("debugOutput")) { 00402 // cout << "Erasing trigger " << *sit << " in " << 00403 // thisNode.ip << ", insertion time is " << sit->getInsertionTime()<< endl; 00404 //} 00405 triggerSet.erase(sit); 00406 updateString = true; 00407 } 00408 } 00409 if (it->second.size() == 0) { 00410 triggerTable.erase(it); 00411 } 00412 } 00413 if (updateString) updateTriggerTableString(); 00414 } else delete msg; 00415 }
void I3::sendQueryReply | ( | const I3Identifier & | id, | |
const I3IPAddress & | add | |||
) | [protected] |
Replies to a query of which server is responsible for the given identifier (this server).
id | I3 identifier of the query | |
add | IP address of requester |
Referenced by deliver(), and sendPacket().
00299 { 00300 I3QueryReplyMessage *pmsg; 00301 I3IPAddress myAddress(thisNode.ip, par("serverPort")); 00302 00303 pmsg = new I3QueryReplyMessage(); 00304 pmsg->setSource(myAddress); 00305 pmsg->setSendingTime(simulation.simTime()); 00306 pmsg->setIdentifier(id); 00307 pmsg->setLength(QUERY_REPLY_L(pmsg)); 00308 sendMessageToUDP(pmsg, add); 00309 }
void I3::forward | ( | OverlayKey * | key, | |
cMessage ** | msg, | |||
NodeHandle * | nextHopNode | |||
) | [protected, virtual] |
Common API function: handles messages from overlay to be forwarded.
method to handle decapsulated KBRdeliver messages from overlay module, should be overwritten in derived application if needed
key | destination key | |
msg | message to forward | |
nextHopNode | next hop |
Reimplemented from BaseApp.
00229 { 00230 numForwardedPackets++; 00231 numForwardedBytes += (*msg)->byteLength(); 00232 00233 BaseApp::forward(key, msg, hint); 00234 }
void I3::updateTriggerTableString | ( | ) | [protected] |
Updates TriggerTable's module display string.
Referenced by handleTimerEvent(), insertTrigger(), and removeTrigger().
00418 { 00419 TriggerTable *table = check_and_cast<TriggerTable*>(parentModule()->submodule("triggerTable")); 00420 table->updateDisplayString(); 00421 }
void I3::finish | ( | ) | [protected, virtual] |
collects statistical data
Reimplemented from BaseApp.
Reimplemented in I3TRTServer.
00429 { 00430 recordScalar("I3 Packets dropped", numDroppedPackets); 00431 recordScalar("I3 Bytes dropped", byteDroppedPackets); 00432 }
I3TriggerTable & I3::getTriggerTable | ( | ) |
Returns the table of inserted triggers.
Referenced by TriggerTable::initialize().
00424 { 00425 return triggerTable; 00426 }
const I3Identifier * I3::findClosestMatch | ( | const I3Identifier & | t | ) | const |
Finds the closest match to t from the stored trigger identifiers.
Note that, in the case that there are many biggest prefix matches, it will only return the first one (bug! - couldn't find efficient way to do)
t | Identifier to be matchesd |
Referenced by sendPacket().
00061 { 00062 int prevDist = 0, nextDist = 0; 00063 00064 00065 if (triggerTable.size() == 0) return 0; 00066 00067 /* find the closest identifier to t */ 00068 /* if no match exists, it gets the next identifier with a bigger key */ 00069 I3TriggerTable::const_iterator it = triggerTable.lower_bound(t); 00070 00071 if (it == triggerTable.end()) { 00072 it--; // if at the end, check last 00073 } 00074 00075 if (it->first == t) return &it->first; // if we found an exact match, no need to bother 00076 00077 if (it != triggerTable.begin()) { // if no smaller keys, begin() is the candidate itself 00078 00079 /* no exact match, check which is closer: */ 00080 /* either where the iterator points to (the next biggest) or the previous one. */ 00081 /* see I3Identifier::distanceTo for distance definition */ 00082 00083 nextDist = it->first.distanceTo(t); 00084 it--; 00085 prevDist = it->first.distanceTo(t); 00086 00087 // if the next one is closest, put iterator back in place 00088 if (nextDist < prevDist) { 00089 it++; 00090 } 00091 } 00092 00093 /* now check if they match in the I3 sense (first prefixLength bits) */ 00094 return (it->first.isMatch(t)) ? &it->first : 0; 00095 }
void I3::insertTrigger | ( | I3Trigger & | t | ) |
Inserts a trigger into I3.
t | Trigger to be inserted |
Referenced by deliver().
00098 { 00099 00100 if (t.getIdentifierStack().size() == 0) { 00101 /* don't bother */ 00102 cout << "Warning: Got trigger " << t << " with size 0 in " << thisNode.ip << endl; 00103 return; 00104 } 00105 00106 t.setInsertionTime(simulation.simTime()); 00107 00108 /* insert packet in triggerTable; */ 00109 /* if it was already there, remove and insert updated copy */ 00110 00111 triggerTable[t.getIdentifier()].erase(t); 00112 triggerTable[t.getIdentifier()].insert(t); 00113 00114 updateTriggerTableString(); 00115 }
void I3::removeTrigger | ( | I3Trigger & | t | ) |
Removes a trigger from I3.
t | Trigger to be removed |
Referenced by deliver().
00118 { 00119 00120 //cout << "Removing trigger at " << id() << endl; 00121 //parentModule()->parentModule()->bubble("Removing trigger"); 00122 00123 if (triggerTable.count(t.getIdentifier()) == 0) return; 00124 00125 set<I3Trigger> &s = triggerTable[t.getIdentifier()]; 00126 00127 s.erase(t); 00128 00129 if (s.size() == 0) triggerTable.erase(t.getIdentifier()); 00130 00131 updateTriggerTableString(); 00132 }
void I3::sendPacket | ( | I3SendPacketMessage * | msg | ) |
Sends a packet through I3.
It checks the trigger table for triggers matching the message's first I3SubIdentifier from the stack. If none are found, the subidentifier is dropped and the packet is routed based on the next remaining one (if no subidentifiers remain, the packet itself is dropped). The matching trigger's own subidentifier stack is then appended to the message stack, and then routed to the first subidentifier of the resulting stack (or sent through UDP if it's an IP address).
msg | Message to be sent |
Referenced by deliver().
00144 { 00145 00146 I3IdentifierStack &idStack = msg->getIdentifierStack(); 00147 00148 if (idStack.size() == 0) { 00149 /* no identifiers left! drop packet */ 00150 /* shouldn't happen (how'd it get here anyway?) */ 00151 numDroppedPackets++; 00152 byteDroppedPackets += msg->length(); 00153 delete msg; 00154 return; 00155 } 00156 00157 I3SubIdentifier id = idStack.peek(); 00158 00159 if (id.getType() == I3SubIdentifier::IPAddress) { 00160 /* shouldn't happen (how'd they find us anyway?) but just in case */ 00161 sendToNode(msg); 00162 } else { 00163 00164 /* if we were asked to reply, send it now */ 00165 if (msg->getSendReply()) { 00166 sendQueryReply(id.getIdentifier(), msg->getSource()); 00167 } 00168 00169 const I3Identifier *i3id = findClosestMatch(id.getIdentifier()); 00170 00171 /* eliminate top of the stack */ 00172 idStack.pop(); 00173 00174 if (!i3id) { 00175 /* no matching ids found in this server, re-route to next id */ 00176 if (idStack.size() == 0) { 00177 /* no identifiers left! drop packet */ 00178 numDroppedPackets++; 00179 byteDroppedPackets += msg->length(); 00180 cout << "Dropped packet at" << thisNode.ip << " to unknown id " << id.getIdentifier() << endl; 00181 delete msg; 00182 return; 00183 } else { 00184 msg->setLength(SEND_PACKET_L(msg)); /* stack size changed, recalculate */ 00185 if (idStack.peek().getType() == I3SubIdentifier::IPAddress) { 00186 msg->getMatchedTrigger().clear(); // not trigger, but direct IP match 00187 sendToNode(msg); 00188 } else { 00189 OverlayKey key = idStack.peek().getIdentifier().asOverlayKey(); 00190 callRoute(key, msg); 00191 } 00192 } 00193 00194 } else { 00195 /* some id found, send to all friends */ 00196 set<I3Trigger> &s = triggerTable[*i3id]; 00197 set<I3Trigger>::iterator it; 00198 00199 for (it = s.begin(); it != s.end(); it++) { 00200 I3SendPacketMessage *newMsg; 00201 cMessage *dupMsg; 00202 00203 newMsg = new I3SendPacketMessage(); 00204 newMsg->setIdentifierStack(idStack); /* create copy */ 00205 newMsg->getIdentifierStack().push(it->getIdentifierStack()); /* append our stuff to the top of the stack */ 00206 dupMsg = check_and_cast<cMessage*>(msg->encapsulatedMsg()->dup()); /* dup msg */ 00207 newMsg->setLength(SEND_PACKET_L(newMsg)); /* stack size changed, recalculate */ 00208 newMsg->encapsulate(dupMsg); 00209 00210 I3SubIdentifier &top = newMsg->getIdentifierStack().peek(); 00211 00212 if (top.getType() == I3SubIdentifier::IPAddress) { 00213 newMsg->setMatchedTrigger(*it); 00214 sendToNode(newMsg); 00215 } else { 00216 OverlayKey key = top.getIdentifier().asOverlayKey(); 00217 callRoute(key, newMsg); 00218 } 00219 } 00220 00221 /* copies sent, erase original */ 00222 delete msg; 00223 00224 } 00225 } 00226 }
void I3::sendToNode | ( | I3SendPacketMessage * | imsg | ) |
Sends packet to matching IP address (used by sendPacket).
imsg | Message to be sent |
Referenced by handleUDPMessage(), and sendPacket().
00135 { 00136 I3IPAddress address; 00137 /* re-route message to a client node */ 00138 address = imsg->getIdentifierStack().peek().getIPAddress(); 00139 imsg->getIdentifierStack().pop(); // pop ip address 00140 sendMessageToUDP(imsg, address); 00141 }
int I3::numDroppedPackets [protected] |
int I3::byteDroppedPackets [protected] |
Referenced by finish(), initializeApp(), and sendPacket().
int I3::numForwardedPackets [protected] |
Referenced by forward(), and initializeApp().
int I3::numForwardedBytes [protected] |
Referenced by forward(), and initializeApp().
int I3::triggerTimeToLive [protected] |
I3TriggerTable I3::triggerTable [protected] |
Table containing inserted triggers.
Referenced by findClosestMatch(), getTriggerTable(), handleTimerEvent(), insertTrigger(), removeTrigger(), and sendPacket().
cMessage* I3::expirationTimer [protected] |