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