BaseApp.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 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 <IPAddressResolver.h>
00025 #include <NotificationBoard.h>
00026 #include <UDPAppBase.h>
00027 #include <UDPSocket.h>
00028 #include <cassert>
00029 
00030 #include <CommonMessages_m.h>
00031 #include <BaseRpc.h>
00032 #include <GlobalNodeListAccess.h>
00033 #include <GlobalStatisticsAccess.h>
00034 #include <UnderlayConfiguratorAccess.h>
00035 
00036 #include "BaseApp.h"
00037 
00038 using namespace std;
00039 
00040 BaseApp::BaseApp()
00041 {
00042     notificationBoard = NULL;
00043 
00044     overlay = NULL;
00045 }
00046 
00047 BaseApp::~BaseApp()
00048 {
00049     finishRpcs();
00050 }
00051 
00052 int BaseApp::numInitStages() const
00053 {
00054     return MAX_STAGE_APP + 1;
00055 }
00056 
00057 void BaseApp::initialize(int stage)
00058 {
00059     CompType compType = getThisCompType();
00060     bool tier = (compType == TIER1_COMP ||
00061                  compType == TIER2_COMP ||
00062                  compType == TIER3_COMP);
00063 
00064     if ((tier && stage == MIN_STAGE_APP) ||
00065         (!tier && stage == MIN_STAGE_COMPONENTS)) {
00066         // fetch parameters
00067         debugOutput = par("debugOutput");
00068 
00069         globalNodeList = GlobalNodeListAccess().get();
00070         underlayConfigurator = UnderlayConfiguratorAccess().get();
00071         globalStatistics = GlobalStatisticsAccess().get();
00072         notificationBoard = NotificationBoardAccess().get();
00073 
00074         // subscribe to the notification board
00075         notificationBoard->subscribe(this, NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00076         notificationBoard->subscribe(this, NF_OVERLAY_NODE_LEAVE);
00077         notificationBoard->subscribe(this, NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00078 
00079         // determine the terminal's transport address
00080         if (getParentModule()->getSubmodule("interfaceTable", 0) != NULL) {
00081             thisNode.setAddress(IPAddressResolver()
00082                           .addressOf(getParentModule()).get4());
00083         } else {
00084             thisNode.setAddress(IPAddressResolver()
00085                           .addressOf(getParentModule()->getParentModule()).get4());
00086         }
00087 
00088         thisNode.setPort(-1);
00089 
00090         WATCH(thisNode);
00091 
00092         // statistics
00093         numOverlaySent = 0;
00094         numOverlayReceived = 0;
00095         bytesOverlaySent = 0;
00096         bytesOverlayReceived = 0;
00097         numUdpSent = 0;
00098         numUdpReceived = 0;
00099         bytesUdpSent = 0;
00100         bytesUdpReceived = 0;
00101 
00102         creationTime = simTime();
00103 
00104         WATCH(numOverlaySent);
00105         WATCH(numOverlayReceived);
00106         WATCH(bytesOverlaySent);
00107         WATCH(bytesOverlayReceived);
00108         WATCH(numUdpSent);
00109         WATCH(numUdpReceived);
00110         WATCH(bytesUdpSent);
00111         WATCH(bytesUdpReceived);
00112 
00113         // init rpcs
00114         initRpcs();
00115     }
00116 
00117     if ((stage >= MIN_STAGE_APP && stage <= MAX_STAGE_APP) ||
00118         (stage >= MIN_STAGE_COMPONENTS && stage <= MAX_STAGE_COMPONENTS)) //TODO
00119         initializeApp(stage);
00120 }
00121 
00122 void BaseApp::initializeApp(int stage)
00123 {
00124     // ...
00125 }
00126 
00127 // Process messages passed up from the overlay.
00128 void BaseApp::handleMessage(cMessage* msg)
00129 {
00130     /*BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00131 
00132     if (rpcMessage!=NULL) {
00133         // process rpc messages
00134         internalHandleRpcMessage(rpcMessage);
00135     } else if (msg->isSelfMessage()) {
00136         // Process self-messages.
00137         handleTimerEvent(msg);
00138     } else*/
00139     if (internalHandleMessage(msg)) return;
00140     if (msg->arrivedOn("from_lowerTier") ||
00141         msg->arrivedOn("direct_in")) {
00142         CompReadyMessage* readyMsg = dynamic_cast<CompReadyMessage*>(msg);
00143         if (readyMsg != NULL) {
00144             handleReadyMessage(readyMsg);
00145             return;
00146         }
00147         // common API
00148         CommonAPIMessage* commonAPIMsg = dynamic_cast<CommonAPIMessage*>(msg);
00149         if (commonAPIMsg != NULL) {
00150             handleCommonAPIMessage(commonAPIMsg);
00151         } else if (msg->arrivedOn("from_lowerTier")) {
00152             // TODO: What kind of messages to we want to measure here?
00153                 cPacket* packet = check_and_cast<cPacket*>(msg);
00154             RECORD_STATS(numOverlayReceived++;
00155                          bytesOverlayReceived += packet->getByteLength());
00156             handleLowerMessage(msg);
00157         }
00158         else delete msg;
00159     } else if (msg->arrivedOn("from_upperTier")) {
00160         handleUpperMessage(msg);
00161     } else if (msg->arrivedOn("udpIn")) {
00162         cPacket* packet = check_and_cast<cPacket*>(msg);
00163         RECORD_STATS(numUdpReceived++; bytesUdpReceived += packet->getByteLength());
00164         // debug message
00165         if (debugOutput && !ev.isDisabled()) {
00166             UDPControlInfo* udpControlInfo =
00167                 check_and_cast<UDPControlInfo*>(msg->getControlInfo());
00168             EV << "[BaseApp:handleMessage() @ " << thisNode.getAddress()
00169             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00170             << "    Received " << *msg << " from "
00171             << udpControlInfo->getSrcAddr() << endl;
00172         }
00173         handleUDPMessage(msg);
00174     } else if (msg->arrivedOn("trace_in")) {
00175         handleTraceMessage(msg);
00176     } else {
00177         delete msg;
00178     }
00179 }
00180 
00181 CompType BaseApp::getThisCompType()
00182 {
00183     std::string name(this->getName());
00184 
00185     if (name == std::string("tier1")) {
00186         return TIER1_COMP;
00187     } else if (name == std::string("tier2")) {
00188         return TIER2_COMP;
00189     } else if (name == std::string("tier3")) {
00190         return TIER3_COMP;
00191     }
00192 
00193     std::string parentName(this->getParentModule()->getName());
00194 
00195     if (parentName == std::string("tier1")) {
00196         return TIER1_COMP;
00197     } else if (parentName == std::string("tier2")) {
00198         return TIER2_COMP;
00199     } else if (parentName == std::string("tier3")) {
00200         return TIER3_COMP;
00201     } else {
00202         throw cRuntimeError("BaseApp::getThisCompType(): "
00203                              "Unknown module type!");
00204     }
00205 
00206     return INVALID_COMP;
00207 }
00208 
00209 void BaseApp::receiveChangeNotification(int category, const cPolymorphic * details)
00210 {
00211     Enter_Method_Silent();
00212     if (category == NF_OVERLAY_TRANSPORTADDRESS_CHANGED) {
00213         handleTransportAddressChangedNotification();
00214     } else if (category == NF_OVERLAY_NODE_LEAVE) {
00215         handleNodeLeaveNotification();
00216     } else if (category == NF_OVERLAY_NODE_GRACEFUL_LEAVE) {
00217         handleNodeGracefulLeaveNotification();
00218     }
00219 }
00220 
00221 void BaseApp::handleTransportAddressChangedNotification()
00222 {
00223     // ...
00224 }
00225 
00226 void BaseApp::handleNodeLeaveNotification()
00227 {
00228     // ...
00229 }
00230 
00231 void BaseApp::handleNodeGracefulLeaveNotification()
00232 {
00233     // ...
00234 }
00235 
00236 void BaseApp::callRoute(const OverlayKey& key, cPacket* msg,
00237                         const std::vector<TransportAddress>& sourceRoute,
00238                         RoutingType routingType)
00239 {
00240     // create route-message (common API)
00241     KBRroute* routeMsg = new KBRroute();
00242     routeMsg->setDestKey(key);
00243 
00244     if (!(sourceRoute.size() == 1 && sourceRoute[0].isUnspecified())) {
00245         routeMsg->setSourceRouteArraySize(sourceRoute.size());
00246         for (uint32_t i = 0; i < sourceRoute.size(); ++i) {
00247             routeMsg->setSourceRoute(i, sourceRoute[i]);
00248         }
00249     }
00250     routeMsg->encapsulate(msg);
00251     routeMsg->setSrcComp(thisCompType);
00252     routeMsg->setDestComp(thisCompType);
00253     routeMsg->setRoutingType(routingType);
00254 
00255     routeMsg->setType(KBR_ROUTE);
00256 
00257     sendDirect(routeMsg, overlay->getCompRpcGate(OVERLAY_COMP));
00258 
00259     // debug message
00260     if (debugOutput && !ev.isDisabled()) {
00261         EV << "[BaseApp::callRoute() @ " << thisNode.getAddress()
00262         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00263         << "    Sending " << *msg
00264         << " to destination key " << key
00265         << " with source route ";
00266 
00267         for (uint32_t i = 0; i < sourceRoute.size(); ++i) {
00268             EV << sourceRoute[i] << " ";
00269         }
00270 
00271         EV << endl;
00272     }
00273 
00274     // count
00275     RECORD_STATS(numOverlaySent++; bytesOverlaySent += msg->getByteLength());
00276 }
00277 
00278 void BaseApp::deliver(OverlayKey& key, cMessage* msg)
00279 {
00280     // deliver...
00281 
00282     delete msg;
00283 }
00284 
00285 void BaseApp::forward(OverlayKey* key, cPacket** msg, NodeHandle* nextHopNode)
00286 {
00287     // usually do nothing
00288 }
00289 
00290 void BaseApp::forwardResponse(const OverlayKey& key, cPacket* msg,
00291                               const NodeHandle& nextHopNode)
00292 {
00293     OverlayCtrlInfo* ctrlInfo =
00294         check_and_cast<OverlayCtrlInfo*>(msg->removeControlInfo());
00295 
00296     //create forwardResponse message (common API)
00297     KBRforward* forwardMsg = new KBRforward();
00298     forwardMsg->setDestKey(key);
00299     forwardMsg->setNextHopNode(nextHopNode);
00300     forwardMsg->setControlInfo(ctrlInfo);
00301     forwardMsg->encapsulate(msg);
00302 
00303     forwardMsg->setType(KBR_FORWARD_RESPONSE);
00304 
00305     if (getThisCompType() == TIER1_COMP) {
00306         send(forwardMsg, "to_lowerTier");
00307     } else {
00308         sendDirect(forwardMsg, overlay->getCompRpcGate(OVERLAY_COMP));
00309     }
00310 }
00311 
00312 void BaseApp::update(const NodeHandle& node, bool joined)
00313 {
00314 }
00315 
00316 void BaseApp::handleCommonAPIMessage(CommonAPIMessage* commonAPIMsg)
00317 {
00318     cPacket* tempMsg = commonAPIMsg->decapsulate();
00319 
00320     // process interface control information
00321     OverlayCtrlInfo* overlayCtrlInfo =
00322         dynamic_cast<OverlayCtrlInfo*>(commonAPIMsg->removeControlInfo());
00323 
00324     if (overlayCtrlInfo != NULL) {
00325         tempMsg->setControlInfo(overlayCtrlInfo);
00326     }
00327 
00328     switch (commonAPIMsg->getType()) {
00329         case KBR_DELIVER:
00330         {
00331             KBRdeliver* apiMsg = dynamic_cast<KBRdeliver*>(commonAPIMsg);
00332             OverlayKey key = apiMsg->getDestKey();
00333             NodeHandle nextHopNode = overlay->getThisNode();
00334 
00335             //first call forward, then deliver
00336             forward(&key, &tempMsg, &nextHopNode);
00337 
00338             if(tempMsg != NULL) {
00339                 //if key or nextHopNode is changed send msg back to overlay
00340                 if ((!key.isUnspecified() && key != apiMsg->getDestKey()) ||
00341                     (!nextHopNode.isUnspecified()
00342                             && nextHopNode != overlay->getThisNode())) {
00343                     forwardResponse(key, tempMsg, nextHopNode);
00344                 }
00345                 else {
00346                     RECORD_STATS(numOverlayReceived++;
00347                                  bytesOverlayReceived += tempMsg->getByteLength());
00348 
00349                     assert(overlayCtrlInfo->getTransportType()
00350                            == ROUTE_TRANSPORT);
00351 
00352                     // debug message
00353                     if (debugOutput) {
00354                         EV << "[BaseApp:handleCommonAPIMessage() @ "
00355                         << thisNode.getAddress() << " ("
00356                         << overlay->getThisNode().getKey().toString(16) << ")]\n"
00357                         << "    Received " << *tempMsg << " from "
00358                         << overlayCtrlInfo->getSrcRoute() << endl;
00359                     }
00360 
00361                     //handle RPC first
00362                     BaseRpcMessage* rpcMessage
00363                         = dynamic_cast<BaseRpcMessage*>(tempMsg);
00364                     if (rpcMessage!=NULL) {
00365                         internalHandleRpcMessage(rpcMessage);
00366                     } else {
00367                         deliver(apiMsg->getDestKey(), tempMsg);
00368                     }
00369                 }
00370             }
00371             break;
00372         }
00373 
00374         case KBR_FORWARD:
00375         {
00376             KBRforward* apiMsg = dynamic_cast<KBRforward*>(commonAPIMsg);
00377             OverlayKey key = apiMsg->getDestKey();
00378             NodeHandle nextHopNode = apiMsg->getNextHopNode();
00379 
00380             forward(&key, &tempMsg, &nextHopNode);
00381 
00382             //if message ist not deleted send it back
00383             if(tempMsg != NULL) {
00384                 if(nextHopNode == apiMsg->getNextHopNode())
00385                     //do we need this?
00386                     nextHopNode = NodeHandle::UNSPECIFIED_NODE;
00387                 forwardResponse(key, tempMsg, nextHopNode);
00388             }
00389             break;
00390         }
00391 
00392         case KBR_UPDATE:
00393         {
00394             KBRupdate* apiMsg = dynamic_cast<KBRupdate*>(commonAPIMsg);
00395             update(apiMsg->getNode(), apiMsg->getJoined());
00396 
00397             break;
00398         }
00399 
00400         default:
00401         {
00402             delete tempMsg;
00403         }
00404     }
00405     delete commonAPIMsg;
00406 }
00407 
00408 void BaseApp::handleUpperMessage(cMessage* msg)
00409 {
00410     delete msg;
00411 }
00412 
00413 void BaseApp::handleLowerMessage(cMessage* msg)
00414 {
00415     delete msg;
00416 }
00417 
00418 void BaseApp::handleUDPMessage(cMessage *msg)
00419 {
00420     delete msg;
00421 }
00422 
00423 void BaseApp::handleReadyMessage(CompReadyMessage* msg)
00424 {
00425     delete msg;
00426 }
00427 
00428 void BaseApp::handleTraceMessage(cMessage* msg)
00429 {
00430     throw cRuntimeError("This application cannot handle trace data. "
00431                          "You have to overwrite handleTraceMessage() in your "
00432                          "application to make trace files work");
00433 }
00434 
00435 void BaseApp::sendMessageToLowerTier(cPacket* msg)
00436 {
00437     RECORD_STATS(numOverlaySent++; bytesOverlaySent += msg->getByteLength());
00438 
00439     send(msg, "to_lowerTier");
00440 }
00441 
00442 void BaseApp::finish()
00443 {
00444     // record scalar data
00445     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00446 
00447     string baseAppName = string("BaseApp (") += string(this->getName())
00448                          += string("): ");
00449 
00450     if (time >= GlobalStatistics::MIN_MEASURED) {
00451         globalStatistics->addStdDev(baseAppName + string("Sent Messages/s to "
00452                                                          "Overlay"),
00453                                     numOverlaySent / time);
00454         globalStatistics->addStdDev(baseAppName +
00455                                     string("Received Messages/s from Overlay"),
00456                                     numOverlayReceived / time);
00457         globalStatistics->addStdDev(baseAppName + string("Sent Bytes/s to "
00458                                                          "Overlay"),
00459                                     bytesOverlaySent / time);
00460         globalStatistics->addStdDev(baseAppName + string("Received Bytes/s "
00461                                                          "from Overlay"),
00462                                     bytesOverlayReceived / time);
00463         globalStatistics->addStdDev(baseAppName + string("Sent Messages/s to "
00464                                                          "UDP"),
00465                                     numUdpSent / time);
00466         globalStatistics->addStdDev(baseAppName +
00467                                     string("Received Messages/s from UDP"),
00468                                     numUdpReceived / time);
00469         globalStatistics->addStdDev(baseAppName + string("Sent Bytes/s to UDP"),
00470                                     bytesUdpSent / time);
00471         globalStatistics->addStdDev(baseAppName + string("Received Bytes/s "
00472                                                          "from UDP"),
00473                                     bytesUdpReceived / time);
00474 
00475     }
00476 
00477     finishApp();
00478 }
00479 
00480 void BaseApp::finishApp()
00481 {
00482     // ...
00483 }
00484 
00485 void BaseApp::bindToPort(int port)
00486 {
00487     EV << "[BaseApp::bindToPort() @ " << thisNode.getAddress()
00488        << ":  Binding to UDP port " << port << endl;
00489 
00490     thisNode.setPort(port);
00491 
00492     cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND);
00493     UDPControlInfo *ctrl = new UDPControlInfo();
00494     ctrl->setSrcPort(port);
00495     ctrl->setSockId(UDPSocket::generateSocketId());
00496     msg->setControlInfo(ctrl);
00497     send(msg, "udpOut");
00498 }
00499 
00500 void BaseApp::sendMessageToUDP(const TransportAddress& destAddr, cPacket *msg)
00501 {
00502     // send message to UDP, with the appropriate control info attached
00503     msg->removeControlInfo();
00504     msg->setKind(UDP_C_DATA);
00505 
00506     UDPControlInfo *ctrl = new UDPControlInfo();
00507     ctrl->setSrcPort(thisNode.getPort());
00508     ctrl->setSrcAddr(thisNode.getAddress());
00509     ctrl->setDestAddr(destAddr.getAddress());
00510     ctrl->setDestPort(destAddr.getPort());
00511     msg->setControlInfo(ctrl);
00512 
00513     if (ev.isGUI()) {
00514         BaseRpcMessage* rpc = dynamic_cast<BaseRpcMessage*>(msg);
00515         if (rpc) rpc->setStatType(APP_DATA_STAT);
00516     }
00517 
00518     // debug message
00519     if (debugOutput) {
00520         EV << "[BaseApp::sendMessageToUDP() @ " << thisNode.getAddress()
00521         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00522         << "    Sending " << *msg << " to " << destAddr.getAddress()
00523         << endl;
00524     }
00525 
00526 
00527     RECORD_STATS(numUdpSent++; bytesUdpSent += msg->getByteLength());
00528     send(msg, "udpOut");
00529 }
00530 
00531 //private
00532 bool BaseApp::internalHandleRpcCall(BaseCallMessage* msg)
00533 {
00534     // if RPC was handled return true, else tell the parent class to handle it
00535     return BaseRpc::internalHandleRpcCall(msg);
00536 }
00537 
00538 void BaseApp::internalHandleRpcResponse(BaseResponseMessage* msg,
00539                                         cPolymorphic* context,
00540                                         int rpcId, simtime_t rtt)
00541 {
00542     // if RPC was handled return true, else tell the parent class to handle it
00543     BaseRpc::internalHandleRpcResponse(msg, context, rpcId, rtt);
00544 }
00545 
00546 void BaseApp::internalSendRouteRpc(BaseRpcMessage* message,
00547                                    const OverlayKey& destKey,
00548                                    const std::vector<TransportAddress>&
00549                                        sourceRoute,
00550                                    RoutingType routingType) {
00551     callRoute(destKey, message, sourceRoute, routingType);
00552 }
00553 
00554 void BaseApp::internalSendRpcResponse(BaseCallMessage* call,
00555                                       BaseResponseMessage* response)
00556 {
00557     // default values for UDP transport
00558     TransportType transportType = UDP_TRANSPORT;
00559     CompType compType = INVALID_COMP;
00560     const TransportAddress* destNode = &TransportAddress::UNSPECIFIED_NODE;//&(call->getSrcNode());
00561     const OverlayKey* destKey = &OverlayKey::UNSPECIFIED_KEY;
00562 
00563     TransportAddress tempNode;
00564 
00565     OverlayCtrlInfo* overlayCtrlInfo =
00566         dynamic_cast<OverlayCtrlInfo*>(call->getControlInfo());
00567 
00568     if (overlayCtrlInfo &&
00569         overlayCtrlInfo->getTransportType() == ROUTE_TRANSPORT) {
00570         //destNode = &(overlayCtrlInfo->getSrcNode());
00571         if (overlayCtrlInfo->getSrcNode().isUnspecified())
00572             destNode = &(overlayCtrlInfo->getLastHop());
00573         else
00574             destNode = &(overlayCtrlInfo->getSrcNode());
00575         transportType = ROUTE_TRANSPORT;
00576         compType = static_cast<CompType>(overlayCtrlInfo->getSrcComp());
00577         if (static_cast<RoutingType>(overlayCtrlInfo->getRoutingType())
00578                 == FULL_RECURSIVE_ROUTING) {
00579             destKey = &(overlayCtrlInfo->getSrcNode().getKey());//&(call->getSrcNode().getKey());
00580             destNode = &NodeHandle::UNSPECIFIED_NODE;
00581         }
00582     } else {
00583         UDPControlInfo* udpCtrlInfo =
00584             check_and_cast<UDPControlInfo*>(call->getControlInfo());
00585 
00586         tempNode = TransportAddress(udpCtrlInfo->getSrcAddr(), udpCtrlInfo->getSrcPort());
00587         destNode = &tempNode;
00588 
00589     }
00590 
00591     sendRpcResponse(transportType, compType,
00592                     *destNode, *destKey, call, response);
00593 }

Generated on Tue Sep 8 17:26:51 2009 for OverSim by  doxygen 1.5.8