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 <OverlayAccess.h>
00033 #include <GlobalNodeListAccess.h>
00034 #include <GlobalStatisticsAccess.h>
00035 #include <UnderlayConfiguratorAccess.h>
00036 
00037 #include "BaseApp.h"
00038 
00039 using namespace std;
00040 
00041 BaseApp::BaseApp()
00042 {
00043     notificationBoard = NULL;
00044 
00045     overlay = NULL;
00046 }
00047 
00048 BaseApp::~BaseApp()
00049 {
00050     finishRpcs();
00051 }
00052 
00053 int BaseApp::numInitStages() const
00054 {
00055     return MAX_STAGE_APP + 1;
00056 }
00057 
00058 void BaseApp::initialize(int stage)
00059 {
00060     CompType compType = getThisCompType();
00061     bool tier = (compType == TIER1_COMP ||
00062                  compType == TIER2_COMP ||
00063                  compType == TIER3_COMP);
00064 
00065     if (stage == REGISTER_STAGE) {
00066         OverlayAccess().get(this)->registerComp(getThisCompType(), this);
00067         return;
00068     }
00069 
00070     if ((tier && stage == MIN_STAGE_APP) ||
00071         (!tier && stage == MIN_STAGE_COMPONENTS)) {
00072         // fetch parameters
00073         debugOutput = par("debugOutput");
00074 
00075         globalNodeList = GlobalNodeListAccess().get();
00076         underlayConfigurator = UnderlayConfiguratorAccess().get();
00077         globalStatistics = GlobalStatisticsAccess().get();
00078         notificationBoard = NotificationBoardAccess().get();
00079 
00080         // subscribe to the notification board
00081         notificationBoard->subscribe(this, NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00082         notificationBoard->subscribe(this, NF_OVERLAY_NODE_LEAVE);
00083         notificationBoard->subscribe(this, NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00084 
00085         // determine the terminal's transport address
00086         if (getParentModule()->getSubmodule("interfaceTable", 0) != NULL) {
00087             thisNode.setAddress(IPAddressResolver()
00088                           .addressOf(getParentModule()));
00089         } else {
00090             thisNode.setAddress(IPAddressResolver()
00091                           .addressOf(getParentModule()->getParentModule()));
00092         }
00093 
00094         thisNode.setPort(-1);
00095 
00096         WATCH(thisNode);
00097 
00098         // statistics
00099         numOverlaySent = 0;
00100         numOverlayReceived = 0;
00101         bytesOverlaySent = 0;
00102         bytesOverlayReceived = 0;
00103         numUdpSent = 0;
00104         numUdpReceived = 0;
00105         bytesUdpSent = 0;
00106         bytesUdpReceived = 0;
00107 
00108         creationTime = simTime();
00109 
00110         WATCH(numOverlaySent);
00111         WATCH(numOverlayReceived);
00112         WATCH(bytesOverlaySent);
00113         WATCH(bytesOverlayReceived);
00114         WATCH(numUdpSent);
00115         WATCH(numUdpReceived);
00116         WATCH(bytesUdpSent);
00117         WATCH(bytesUdpReceived);
00118 
00119         // init rpcs
00120         initRpcs();
00121     }
00122 
00123     if ((stage >= MIN_STAGE_APP && stage <= MAX_STAGE_APP) ||
00124         (stage >= MIN_STAGE_COMPONENTS && stage <= MAX_STAGE_COMPONENTS)) //TODO
00125         initializeApp(stage);
00126 }
00127 
00128 void BaseApp::initializeApp(int stage)
00129 {
00130     // ...
00131 }
00132 
00133 // Process messages passed up from the overlay.
00134 void BaseApp::handleMessage(cMessage* msg)
00135 {
00136     if (internalHandleMessage(msg)) {
00137         return;
00138     }
00139 
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 void BaseApp::sendReadyMessage(bool ready)
00442 {
00443     CompReadyMessage* msg = new CompReadyMessage();
00444     msg->setReady(ready);
00445     msg->setComp(getThisCompType());
00446 
00447     overlay->sendMessageToAllComp(msg, getThisCompType());
00448 }
00449 
00450 void BaseApp::finish()
00451 {
00452     // record scalar data
00453     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00454 
00455     string baseAppName = string("BaseApp (") += string(this->getName())
00456                          += string("): ");
00457 
00458     if (time >= GlobalStatistics::MIN_MEASURED) {
00459         globalStatistics->addStdDev(baseAppName + string("Sent Messages/s to "
00460                                                          "Overlay"),
00461                                     numOverlaySent / time);
00462         globalStatistics->addStdDev(baseAppName +
00463                                     string("Received Messages/s from Overlay"),
00464                                     numOverlayReceived / time);
00465         globalStatistics->addStdDev(baseAppName + string("Sent Bytes/s to "
00466                                                          "Overlay"),
00467                                     bytesOverlaySent / time);
00468         globalStatistics->addStdDev(baseAppName + string("Received Bytes/s "
00469                                                          "from Overlay"),
00470                                     bytesOverlayReceived / time);
00471         globalStatistics->addStdDev(baseAppName + string("Sent Messages/s to "
00472                                                          "UDP"),
00473                                     numUdpSent / time);
00474         globalStatistics->addStdDev(baseAppName +
00475                                     string("Received Messages/s from UDP"),
00476                                     numUdpReceived / time);
00477         globalStatistics->addStdDev(baseAppName + string("Sent Bytes/s to UDP"),
00478                                     bytesUdpSent / time);
00479         globalStatistics->addStdDev(baseAppName + string("Received Bytes/s "
00480                                                          "from UDP"),
00481                                     bytesUdpReceived / time);
00482 
00483     }
00484 
00485     finishApp();
00486 }
00487 
00488 void BaseApp::finishApp()
00489 {
00490     // ...
00491 }
00492 
00493 void BaseApp::bindToPort(int port)
00494 {
00495     EV << "[BaseApp::bindToPort() @ " << thisNode.getAddress()
00496        << ":  Binding to UDP port " << port << endl;
00497 
00498     thisNode.setPort(port);
00499 
00500     cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND);
00501     UDPControlInfo *ctrl = new UDPControlInfo();
00502     ctrl->setSrcPort(port);
00503     ctrl->setSockId(UDPSocket::generateSocketId());
00504     msg->setControlInfo(ctrl);
00505     send(msg, "udpOut");
00506 }
00507 
00508 void BaseApp::sendMessageToUDP(const TransportAddress& destAddr, cPacket *msg)
00509 {
00510     // send message to UDP, with the appropriate control info attached
00511     msg->removeControlInfo();
00512     msg->setKind(UDP_C_DATA);
00513 
00514     UDPControlInfo *ctrl = new UDPControlInfo();
00515     ctrl->setSrcPort(thisNode.getPort());
00516     ctrl->setSrcAddr(thisNode.getAddress());
00517     ctrl->setDestAddr(destAddr.getAddress());
00518     ctrl->setDestPort(destAddr.getPort());
00519     msg->setControlInfo(ctrl);
00520 
00521     if (ev.isGUI()) {
00522         BaseRpcMessage* rpc = dynamic_cast<BaseRpcMessage*>(msg);
00523         if (rpc) rpc->setStatType(APP_DATA_STAT);
00524     }
00525 
00526     // debug message
00527     if (debugOutput) {
00528         EV << "[BaseApp::sendMessageToUDP() @ " << thisNode.getAddress()
00529         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00530         << "    Sending " << *msg << " to " << destAddr.getAddress()
00531         << endl;
00532     }
00533 
00534 
00535     RECORD_STATS(numUdpSent++; bytesUdpSent += msg->getByteLength());
00536     send(msg, "udpOut");
00537 }
00538 
00539 //private
00540 bool BaseApp::internalHandleRpcCall(BaseCallMessage* msg)
00541 {
00542     // if RPC was handled return true, else tell the parent class to handle it
00543     return BaseRpc::internalHandleRpcCall(msg);
00544 }
00545 
00546 void BaseApp::internalHandleRpcResponse(BaseResponseMessage* msg,
00547                                         cPolymorphic* context,
00548                                         int rpcId, simtime_t rtt)
00549 {
00550     // if RPC was handled return true, else tell the parent class to handle it
00551     BaseRpc::internalHandleRpcResponse(msg, context, rpcId, rtt);
00552 }
00553 
00554 void BaseApp::internalSendRouteRpc(BaseRpcMessage* message,
00555                                    const OverlayKey& destKey,
00556                                    const std::vector<TransportAddress>&
00557                                        sourceRoute,
00558                                    RoutingType routingType) {
00559     callRoute(destKey, message, sourceRoute, routingType);
00560 }
00561 
00562 void BaseApp::internalSendRpcResponse(BaseCallMessage* call,
00563                                       BaseResponseMessage* response)
00564 {
00565     // default values for UDP transport
00566     TransportType transportType = UDP_TRANSPORT;
00567     CompType compType = INVALID_COMP;
00568     const TransportAddress* destNode = &TransportAddress::UNSPECIFIED_NODE;//&(call->getSrcNode());
00569     const OverlayKey* destKey = &OverlayKey::UNSPECIFIED_KEY;
00570 
00571     TransportAddress tempNode;
00572 
00573     OverlayCtrlInfo* overlayCtrlInfo =
00574         dynamic_cast<OverlayCtrlInfo*>(call->getControlInfo());
00575 
00576     if (overlayCtrlInfo &&
00577         overlayCtrlInfo->getTransportType() == ROUTE_TRANSPORT) {
00578         //destNode = &(overlayCtrlInfo->getSrcNode());
00579         if (overlayCtrlInfo->getSrcNode().isUnspecified())
00580             destNode = &(overlayCtrlInfo->getLastHop());
00581         else
00582             destNode = &(overlayCtrlInfo->getSrcNode());
00583         transportType = ROUTE_TRANSPORT;
00584         compType = static_cast<CompType>(overlayCtrlInfo->getSrcComp());
00585         if (static_cast<RoutingType>(overlayCtrlInfo->getRoutingType())
00586                 == FULL_RECURSIVE_ROUTING) {
00587             destKey = &(overlayCtrlInfo->getSrcNode().getKey());//&(call->getSrcNode().getKey());
00588             destNode = &NodeHandle::UNSPECIFIED_NODE;
00589         }
00590     } else {
00591         UDPControlInfo* udpCtrlInfo =
00592             check_and_cast<UDPControlInfo*>(call->getControlInfo());
00593 
00594         tempNode = TransportAddress(udpCtrlInfo->getSrcAddr(), udpCtrlInfo->getSrcPort());
00595         destNode = &tempNode;
00596 
00597     }
00598 
00599     sendRpcResponse(transportType, compType,
00600                     *destNode, *destKey, call, response);
00601 }
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3