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