BaseRpc.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 
00027 #include <vector>
00028 #include <string>
00029 #include <cassert>
00030 
00031 #include <CommonMessages_m.h>
00032 #include <UnderlayConfiguratorAccess.h>
00033 #include <GlobalStatisticsAccess.h>
00034 #include <NeighborCache.h>
00035 #include <CryptoModule.h>
00036 #include <Vivaldi.h>
00037 #include <OverlayAccess.h>
00038 
00039 #include "BaseRpc.h"
00040 #include "RpcMacros.h"
00041 
00042 
00043 //------------------------------------------------------------------------
00044 //--- Initialization & finishing -----------------------------------------
00045 //------------------------------------------------------------------------
00046 
00047 
00048 //------------------------------------------------------------------------
00049 //--- RPC Handling -------------------------------------------------------
00050 //------------------------------------------------------------------------
00051 
00052 BaseRpc::BaseRpc()
00053 {
00054     defaultRpcListener = NULL;
00055     neighborCache = NULL;
00056     cryptoModule = NULL;
00057 }
00058 
00059 bool BaseRpc::internalHandleMessage(cMessage* msg)
00060 {
00061     // process self-messages and RPC-timeouts
00062     if (msg->isSelfMessage()) {
00063         // process rpc self-messages
00064         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00065         if (rpcMessage != NULL) {
00066             internalHandleRpcMessage(rpcMessage);
00067             return true;
00068         }
00069         // process all other self-messages
00070         handleTimerEvent(msg);
00071         return true;
00072     }
00073 
00074     // process RPC messages
00075     BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00076     if (rpcMessage != NULL) {
00077         internalHandleRpcMessage(rpcMessage);
00078         return true;
00079     }
00080 
00081     // other messages are processed by derived classes
00082     // (e.g. BaseOverlay / BaseApp)
00083     return false;
00084 }
00085 
00086 void BaseRpc::handleTimerEvent(cMessage* msg)
00087 {
00088     // ...
00089 }
00090 
00091 //private
00092 void BaseRpc::initRpcs()
00093 {
00094     // set friend modules
00095     globalStatistics = GlobalStatisticsAccess().get();
00096 
00097     rpcUdpTimeout = par("rpcUdpTimeout");
00098     rpcKeyTimeout = par("rpcKeyTimeout");
00099     optimizeTimeouts = par("optimizeTimeouts");
00100     rpcExponentialBackoff = par("rpcExponentialBackoff");
00101 
00102     rpcsPending = 0;
00103     rpcStates.clear();
00104 
00105     defaultRpcListener = new RpcListener();
00106 
00107     //set ping cache
00108     numPingSent = 0;
00109     bytesPingSent = 0;
00110     numPingResponseSent = 0;
00111     bytesPingResponseSent = 0;
00112 
00113     WATCH(numPingSent);
00114     WATCH(bytesPingSent);
00115     WATCH(numPingResponseSent);
00116     WATCH(bytesPingResponseSent);
00117 
00118     // set overlay pointer
00119     overlay = OverlayAccess().get(this);
00120 
00121     // register component
00122     thisCompType = getThisCompType();
00123     overlay->registerComp(thisCompType, this);
00124 
00125     // get pointer to the neighborCache
00126     cModule *mod = getParentModule();
00127     while (neighborCache == NULL) {
00128         neighborCache = (NeighborCache*)mod->getSubmodule("neighborCache");
00129         mod = mod->getParentModule();
00130         if (!mod)
00131             throw cRuntimeError("BaseRpc::initRpc: "
00132                                 "Module type contains no NeighborCache!");
00133     }
00134 
00135     // get pointer to the cryptoModule
00136     mod = getParentModule();
00137     cryptoModule = NULL;
00138     while (cryptoModule == NULL) {
00139         cryptoModule = (CryptoModule*)mod->getSubmodule("cryptoModule");
00140         mod = mod->getParentModule();
00141         if (!mod)
00142             throw cRuntimeError("BaseRpc::initRpc: CryptoModule not found!");
00143     }
00144 }
00145 
00146 //private
00147 void BaseRpc::finishRpcs()
00148 {
00149     cancelAllRpcs();
00150 
00151     // delete default rpc listener
00152     if (defaultRpcListener != NULL) {
00153         delete defaultRpcListener;
00154         defaultRpcListener = NULL;
00155     }
00156 }
00157 
00158 void BaseRpc::cancelAllRpcs()
00159 {
00160     // stop all rpcs
00161     for (RpcStates::iterator i = rpcStates.begin();
00162         i != rpcStates.end(); i++) {
00163         cancelAndDelete(i->second.callMsg);
00164         cancelAndDelete(i->second.timeoutMsg);
00165         delete i->second.dest;
00166         i->second.dest = NULL;
00167         delete i->second.context;
00168         i->second.context = NULL;
00169     }
00170     rpcStates.clear();
00171 }
00172 
00173 uint32_t BaseRpc::sendRpcCall(TransportType transportType,
00174                               CompType destComp,
00175                               const TransportAddress& dest,
00176                               const OverlayKey& destKey,
00177                               BaseCallMessage* msg,
00178                               cPolymorphic* context,
00179                               RoutingType routingType,
00180                               simtime_t timeout,
00181                               int retries,
00182                               int rpcId,
00183                               RpcListener* rpcListener)
00184 {
00185     // create nonce, timeout and set default parameters
00186     uint32_t nonce;
00187     do {
00188         nonce = intuniform(1, 2147483647);
00189     } while (rpcStates.count(nonce) > 0);
00190 
00191     if (timeout == -1) {
00192         switch (transportType) {
00193         case INTERNAL_TRANSPORT:
00194             timeout = 0;
00195             break;
00196         case UDP_TRANSPORT:
00197             if (optimizeTimeouts) {
00198                 timeout = neighborCache->getNodeTimeout(dest);
00199                 if (timeout == -1) timeout = rpcUdpTimeout;
00200             } else timeout = rpcUdpTimeout;
00201             break;
00202         case ROUTE_TRANSPORT:
00203             timeout = (destKey.isUnspecified() ?
00204                        rpcUdpTimeout :
00205                        rpcKeyTimeout);
00206             break;
00207         default:
00208             throw cRuntimeError("BaseRpc::sendRpcMessage(): "
00209                                 "Unknown RpcTransportType!");
00210         }
00211     }
00212 
00213     if (rpcListener == NULL)
00214         rpcListener = defaultRpcListener;
00215 
00216     // create state
00217     RpcState state;
00218     state.id = rpcId;
00219     state.timeSent = simTime();
00220     state.dest = dest.dup();
00221     state.destKey = destKey;
00222     state.srcComp = getThisCompType();
00223     state.destComp = destComp;
00224     state.listener = rpcListener;
00225     state.timeoutMsg = new RpcTimeoutMessage();
00226     state.timeoutMsg->setNonce(nonce);
00227     state.retries = retries;
00228     state.rto = timeout;
00229     state.transportType = transportType;
00230     //state.transportType = (destKey.isUnspecified() && (dest.getSourceRouteSize() == 0)
00231     //        ? UDP_TRANSPORT : transportType); //test
00232     state.routingType = routingType;
00233     state.context = context;
00234 
00235     if (rpcStates.count(nonce) > 0)
00236         throw cRuntimeError("RPC nonce collision");
00237 
00238     // set message parameters
00239     msg->setNonce(nonce);
00240     if (transportType == ROUTE_TRANSPORT)
00241         msg->setSrcNode(overlay->getThisNode());
00242     else
00243         msg->setSrcNode(thisNode);
00244     msg->setType(RPC);
00245 
00246     // sign the message
00247     // if (transportType != INTERNAL_TRANSPORT) cryptoModule->signMessage(msg);
00248 
00249     // save copy of call message in RpcState
00250     state.callMsg = dynamic_cast<BaseCallMessage*>(msg->dup());
00251     assert(!msg->getEncapsulatedPacket() || !msg->getEncapsulatedPacket()->getControlInfo());
00252 
00253     // register state
00254     rpcStates[nonce] = state;
00255 
00256     // schedule timeout message
00257     if (state.rto != 0)
00258         scheduleAt(simTime() + state.rto, state.timeoutMsg);
00259 
00260     // TODO: cleanup code to have only one type for source routes
00261     std::vector<TransportAddress> sourceRoute;
00262     sourceRoute.push_back(dest);
00263     if (dest.getSourceRouteSize() > 0) {
00264         state.transportType = transportType = ROUTE_TRANSPORT;
00265         sourceRoute.insert(sourceRoute.begin(), dest.getSourceRoute().rend(),
00266                           dest.getSourceRoute().rbegin());
00267         // remove the original source route from the destination
00268         sourceRoute.back().clearSourceRoute();
00269     }
00270     sendRpcMessageWithTransport(transportType, destComp, routingType,
00271                                 sourceRoute, destKey, msg);
00272 
00273     return nonce;
00274 }
00275 
00276 
00277 //public
00278 void BaseRpc::cancelRpcMessage(uint32_t nonce)
00279 {
00280     if (rpcStates.count(nonce)==0)
00281         return;
00282     RpcState state = rpcStates[nonce];
00283     rpcStates.erase(nonce);
00284     cancelAndDelete(state.callMsg);
00285     cancelAndDelete(state.timeoutMsg);
00286     delete state.dest;
00287     state.dest = NULL;
00288     delete state.context;
00289     state.context = NULL;
00290 }
00291 
00292 //protected
00293 void BaseRpc::internalHandleRpcMessage(BaseRpcMessage* msg)
00294 {
00295     // check if this is a rpc call message
00296     BaseCallMessage* rpCall = dynamic_cast<BaseCallMessage*>(msg);
00297     if (rpCall != NULL) {
00298         // verify the message signature
00299         //cryptoModule->verifyMessage(msg);
00300 
00301         OverlayCtrlInfo* overlayCtrlInfo =
00302             dynamic_cast<OverlayCtrlInfo*>(msg->getControlInfo());
00303 
00304         if (overlayCtrlInfo && overlayCtrlInfo->getSrcRoute().isUnspecified() &&
00305             (!overlayCtrlInfo->getLastHop().isUnspecified())) {
00306             overlayCtrlInfo->setSrcRoute(NodeHandle(msg->getSrcNode().getKey(),
00307                                                overlayCtrlInfo->getLastHop()));
00308         }
00309 
00310         bool rpcHandled = true;
00311         if (!handleRpcCall(rpCall)) rpcHandled = internalHandleRpcCall(rpCall);
00312         if (!rpcHandled) {
00313             EV << "[BaseRpc::internalHandleRpcMessage() @ " << thisNode.getIp()
00314                << " (" << thisNode.getKey().toString(16) << ")]\n"
00315                << "    Error: RPC '" << msg->getFullName()<< "' was not handled"
00316                << endl;
00317             delete msg;
00318         }
00319         return;
00320     }
00321 
00322     // get nonce
00323     int nonce = msg->getNonce();
00324 
00325     // nonce known? no -> delete message and return
00326     if (rpcStates.count(nonce)==0) {
00327         EV << "[BaseRpc::internalHandleRpcMessage() @ " << thisNode.getIp()
00328            << " " << thisNode.getKey().toString(16) << ")]\n"
00329            << "    RPC: Nonce Unknown"
00330            << endl;
00331         delete msg;
00332         return;
00333     }
00334 
00335     // get state and remove from map
00336     RpcState state = rpcStates[nonce];
00337     rpcStates.erase(nonce);
00338 
00339     // is timeout message?
00340     if (msg->isSelfMessage() &&
00341         (dynamic_cast<RpcTimeoutMessage*>(msg) != NULL)) {
00342         // yes-> inform listener
00343 
00344         // retry?
00345         state.retries--;
00346         if (state.retries>=0) {
00347             // TODO: cleanup code to have only one type for source routes
00348             std::vector<TransportAddress> sourceRoute;
00349             sourceRoute.push_back(*state.dest);
00350             if (state.dest->getSourceRouteSize() > 0) {
00351                 sourceRoute.insert(sourceRoute.begin(),
00352                                    state.dest->getSourceRoute().rend(),
00353                                    state.dest->getSourceRoute().rbegin());
00354                 // remove the original source route from the destination
00355                 sourceRoute.back().clearSourceRoute();
00356             }
00357 
00358             sendRpcMessageWithTransport(state.transportType, state.destComp,
00359                                         state.routingType,
00360                                         sourceRoute,
00361                                         state.destKey,
00362                                         dynamic_cast<BaseCallMessage*>
00363                                         (state.callMsg->dup()));
00364 
00365             if (rpcExponentialBackoff) {
00366                 state.rto *= 2;
00367             }
00368 
00369             if (state.rto!=0)
00370                 scheduleAt(simTime() + state.rto, msg);
00371 
00372             state.timeSent = simTime();
00373             rpcStates[nonce] = state;
00374             return;
00375         }
00376         EV << "[BaseRpc::internalHandleRpcMessage() @ " << thisNode.getIp()
00377            << " " << thisNode.getKey().toString(16) << ")]\n"
00378            << "    RPC timeout (" << state.callMsg->getName() << ")"
00379            << endl;
00380 
00381         // inform neighborcache
00382         if (state.transportType == UDP_TRANSPORT ||
00383             (!state.dest->isUnspecified() && state.destKey.isUnspecified())) {
00384             neighborCache->setNodeTimeout(*state.dest);
00385         }
00386 
00387         // inform listener
00388         if (state.listener != NULL)
00389             state.listener->handleRpcTimeout(state);
00390 
00391         // inform overlay
00392         internalHandleRpcTimeout(state.callMsg, *state.dest, state.context,
00393                                  state.id, state.destKey);
00394         handleRpcTimeout(state);
00395 
00396     } else { // no-> handle rpc response
00397 
00398         // verify the message signature
00399         //cryptoModule->verifyMessage(msg);
00400 
00401         OverlayCtrlInfo* overlayCtrlInfo =
00402             dynamic_cast<OverlayCtrlInfo*>(msg->getControlInfo());
00403 
00404         if (overlayCtrlInfo && overlayCtrlInfo->getSrcRoute().isUnspecified() &&
00405                  (!overlayCtrlInfo->getLastHop().isUnspecified())) {
00406              overlayCtrlInfo->setSrcRoute(NodeHandle(msg->getSrcNode().getKey(),
00407                                                 overlayCtrlInfo->getLastHop()));
00408         }
00409 
00410         // drop responses with wrong source key
00411         if (state.destKey.isUnspecified()) {
00412             const NodeHandle* stateHandle =
00413                 dynamic_cast<const NodeHandle*>(state.dest);
00414                 if (stateHandle != NULL &&
00415                     stateHandle->getKey() != msg->getSrcNode().getKey()) {
00416 
00417                     EV << "[BaseRpc::internalHandleRpcMessage() @ "
00418                        << thisNode.getIp()
00419                        << " " << thisNode.getKey().toString(16) << ")]\n"
00420                        << "    Dropping RPC: Invalid source key"
00421                        << endl;
00422 
00423                     // restore state to trigger timeout message
00424                     rpcStates[nonce] = state;
00425                     delete msg;
00426                     return;
00427                 }
00428         }
00429 
00430         // get parameters
00431         simtime_t rtt = simTime() - state.timeSent;
00432         BaseResponseMessage* response
00433             = dynamic_cast<BaseResponseMessage*>(msg);
00434 
00435         //if (state.transportType == UDP_TRANSPORT)
00436         //    globalStatistics->recordOutVector("BaseRpc: UDP Round Trip Time",
00437         //                                      rtt);
00438 
00439         // neighborCache/ncs stuff
00440         if (state.transportType == UDP_TRANSPORT ||
00441             (state.transportType != INTERNAL_TRANSPORT &&
00442              response->getCallHopCount() == 1)) {
00443             unsigned int ncsArraySize = response->getNcsInfoArraySize();
00444             if (ncsArraySize > 0) {
00445                 std::vector<double> tempCoords(ncsArraySize);
00446                 for (uint8_t i = 0; i < ncsArraySize; i++) {
00447                     tempCoords[i] = response->getNcsInfo(i);
00448                 }
00449                 AbstractNcsNodeInfo* coords =
00450                     neighborCache->getNcsAccess().createNcsInfo(tempCoords);
00451 
00452                 OverlayCtrlInfo* ctrlInfo =
00453                     dynamic_cast<OverlayCtrlInfo*>(response->getControlInfo());
00454 
00455                 neighborCache->updateNode(response->getSrcNode(), rtt,
00456                                           (ctrlInfo ?
00457                                            ctrlInfo->getSrcRoute() :
00458                                            NodeHandle::UNSPECIFIED_NODE),
00459                                            coords);
00460             } else {
00461                 neighborCache->updateNode(response->getSrcNode(), rtt);
00462             }
00463         }
00464 
00465         // inform listener
00466         if (state.listener != NULL)
00467             state.listener->handleRpcResponse(response, state, rtt);
00468 
00469         // inform overlay
00470         internalHandleRpcResponse(response, state.context, state.id, rtt);
00471         handleRpcResponse(response, state, rtt);
00472 
00473         // delete response
00474         delete response->removeControlInfo();
00475         delete response;
00476     }
00477 
00478     // delete messages
00479     delete state.callMsg;
00480     cancelAndDelete(state.timeoutMsg);
00481     delete state.dest;
00482 
00483     // clean up pointers
00484     state.dest = NULL;
00485     state.context = NULL;
00486     state.callMsg = NULL;
00487     state.timeoutMsg = NULL;
00488 }
00489 
00490 //private
00491 bool BaseRpc::internalHandleRpcCall(BaseCallMessage* msg)
00492 {
00493     RPC_SWITCH_START( msg );
00494     RPC_DELEGATE( Ping, pingRpcCall );
00495     RPC_SWITCH_END( );
00496 
00497     return RPC_HANDLED;
00498 }
00499 
00500 void BaseRpc::internalHandleRpcResponse(BaseResponseMessage* msg,
00501                                         cPolymorphic* context,
00502                                         int rpcId, simtime_t rtt)
00503 {
00504     // call rpc stubs
00505     RPC_SWITCH_START( msg );
00506     RPC_ON_RESPONSE( Ping ) {
00507         pingRpcResponse(_PingResponse, context, rpcId, rtt);
00508     }
00509     RPC_SWITCH_END( );
00510 }
00511 
00512 void BaseRpc::internalHandleRpcTimeout(BaseCallMessage* msg,
00513                                        const TransportAddress& dest,
00514                                        cPolymorphic* context,
00515                                        int rpcId, const OverlayKey& destKey)
00516 {
00517     RPC_SWITCH_START( msg ) {
00518         RPC_ON_CALL( Ping ) {
00519             pingRpcTimeout(_PingCall, dest, context, rpcId);
00520         }
00521     }
00522     RPC_SWITCH_END( )
00523 }
00524 
00525 //virtual protected
00526 bool BaseRpc::handleRpcCall(BaseCallMessage* msg)
00527 {
00528     return false;
00529 }
00530 
00531 void BaseRpc::sendRpcResponse(TransportType transportType,
00532                               CompType compType,
00533                               const TransportAddress& dest,
00534                               const OverlayKey& destKey,
00535                               BaseCallMessage* call,
00536                               BaseResponseMessage* response)
00537 {
00538     if (call == NULL || response == NULL) {
00539         throw cRuntimeError("call or response = NULL!");
00540     }
00541 
00542     // vivaldi: set coordinates and error estimation in response
00543     if (neighborCache->sendBackOwnCoords()) { //TODO only for directly sent msgs
00544         std::vector<double> nodeCoord =
00545             neighborCache->getNcsAccess().getOwnNcsInfo();
00546 
00547         response->setNcsInfoArraySize(nodeCoord.size());
00548         for (uint32_t i = 0; i < nodeCoord.size(); i++) {
00549             response->setNcsInfo(i, nodeCoord[i]);
00550         }
00551     }
00552 
00553     assert(transportType == INTERNAL_TRANSPORT ||
00554            !dest.isUnspecified() ||
00555            !destKey.isUnspecified());
00556 
00557     if (transportType == ROUTE_TRANSPORT)
00558         response->setSrcNode(overlay->getThisNode());
00559     else
00560         response->setSrcNode(thisNode);
00561     response->setType(RPC);
00562     response->setNonce(call->getNonce());
00563     response->setStatType(call->getStatType());
00564 
00565     RoutingType routingType = NO_OVERLAY_ROUTING;
00566     OverlayCtrlInfo* overlayCtrlInfo = NULL;
00567     if (dynamic_cast<OverlayCtrlInfo*>(call->getControlInfo())) {
00568         overlayCtrlInfo =
00569             static_cast<OverlayCtrlInfo*>(call->removeControlInfo());
00570         response->setCallHopCount(overlayCtrlInfo->getHopCount());
00571     } else {
00572         delete call->removeControlInfo();
00573         response->setCallHopCount(1); // one udp hop (?)
00574     }
00575 
00576     // source routing
00577     std::vector<TransportAddress> sourceRoute;
00578     if (overlayCtrlInfo && transportType == ROUTE_TRANSPORT) {
00579         routingType =
00580             static_cast<RoutingType>(overlayCtrlInfo->getRoutingType());
00581         for (uint32_t i = overlayCtrlInfo->getVisitedHopsArraySize(); i > 0; --i) {
00582             sourceRoute.push_back(overlayCtrlInfo->getVisitedHops(i - 1));
00583         }
00584     }
00585 
00586     if (sourceRoute.size() == 0) {
00587         // empty visited hops list => direct response
00588         sourceRoute.push_back(dest);
00589     }
00590 
00591     sendRpcMessageWithTransport(transportType, compType,
00592                                 routingType, sourceRoute,
00593                                 destKey, response);
00594     delete overlayCtrlInfo;
00595     delete call;
00596 }
00597 
00598 //protected
00599 void BaseRpc::sendRpcResponse(BaseCallMessage* call,
00600                               BaseResponseMessage* response)
00601 {
00602     const TransportAddress* destNode = &(call->getSrcNode());
00603     const OverlayKey* destKey = &(call->getSrcNode().getKey());
00604 
00605     OverlayCtrlInfo* overlayCtrlInfo =
00606         dynamic_cast<OverlayCtrlInfo*>(call->getControlInfo());
00607 
00608     // "magic" transportType selection: internal
00609     if (overlayCtrlInfo &&
00610         overlayCtrlInfo->getTransportType() == INTERNAL_TRANSPORT) {
00611         sendRpcResponse(INTERNAL_TRANSPORT,
00612                         static_cast<CompType>(overlayCtrlInfo->getSrcComp()),
00613                         *destNode, *destKey, call, response);
00614     } else {
00615         internalSendRpcResponse(call, response);
00616     }
00617 }
00618 
00619 void BaseRpc::sendRpcMessageWithTransport(TransportType transportType,
00620                                           CompType destComp,
00621                                           RoutingType routingType,
00622                                           const std::vector<TransportAddress>& sourceRoute,
00623                                           const OverlayKey& destKey,
00624                                           BaseRpcMessage* message)
00625 {
00626     switch (transportType) {
00627     case UDP_TRANSPORT: {
00628         sendMessageToUDP(sourceRoute[0], message);
00629         break;
00630     }
00631     case ROUTE_TRANSPORT: {
00632         internalSendRouteRpc(message, destKey,
00633                              sourceRoute, routingType);
00634         break;
00635     }
00636     case INTERNAL_TRANSPORT: {
00637         cGate *destCompGate = overlay->getCompRpcGate(destComp);
00638         if (destCompGate == NULL) {
00639             throw cRuntimeError("BaseRpc::sendRpcMessageWithTransport():"
00640                                     " INTERNAL_RPC to unknown RpcCompType!");
00641         }
00642         OverlayCtrlInfo *overlayCtrlInfo = new OverlayCtrlInfo();
00643         overlayCtrlInfo->setSrcComp(getThisCompType());
00644         overlayCtrlInfo->setDestComp(destComp);
00645         overlayCtrlInfo->setTransportType(INTERNAL_TRANSPORT);
00646         message->setControlInfo(overlayCtrlInfo);
00647         sendDirect(message, destCompGate);
00648         break;
00649     }
00650     default:
00651         throw cRuntimeError("BaseRpc::sendRpcMessageWithTransport: "
00652                                 "invalid transportType!");
00653         break;
00654     }
00655 }
00656 
00657 // ping RPC stuff
00658 void BaseRpc::pingResponse(PingResponse* response, cPolymorphic* context,
00659                            int rpcId, simtime_t rtt)
00660 {
00661 }
00662 
00663 void BaseRpc::pingTimeout(PingCall* call, const TransportAddress& dest,
00664                           cPolymorphic* context, int rpcId)
00665 {
00666 }
00667 
00668 void BaseRpc::pingRpcCall(PingCall* call)
00669 {
00670     std::string pongName(call->getName());
00671     if (pongName == "PING")
00672         pongName = "PONG";
00673     else {
00674         pongName = "PONG: [ ";
00675         pongName += call->getName();
00676         pongName += " ]";
00677     }
00678 
00679     PingResponse* response = new PingResponse(pongName.c_str());
00680     response->setBitLength(PINGRESPONSE_L(response));
00681     RECORD_STATS(numPingResponseSent++; bytesPingResponseSent +=
00682         response->getByteLength());
00683 
00684     sendRpcResponse(call, response );
00685 }
00686 
00687 void BaseRpc::pingRpcResponse(PingResponse* response,
00688                               cPolymorphic* context, int rpcId, simtime_t rtt)
00689 {
00690     pingResponse(response, context, rpcId, rtt);
00691 }
00692 
00693 void BaseRpc::pingRpcTimeout(PingCall* pingCall,
00694                              const TransportAddress& dest,
00695                              cPolymorphic* context,
00696                              int rpcId)
00697 {
00698     pingTimeout(pingCall, dest, context, rpcId);
00699 }
00700 
00701 int BaseRpc::pingNode(const TransportAddress& dest, simtime_t timeout,
00702                        int retries, cPolymorphic* context,
00703                        const char* caption, RpcListener* rpcListener,
00704                        int rpcId, TransportType transportType)
00705 {
00706     PingCall* call = new PingCall(caption);
00707     call->setBitLength(PINGCALL_L(call));
00708     RECORD_STATS(numPingSent++; bytesPingSent += call->getByteLength());
00709 
00710     if (transportType == UDP_TRANSPORT ||
00711         (transportType != ROUTE_TRANSPORT &&
00712          getThisCompType() == OVERLAY_COMP)) {
00713         return sendUdpRpcCall(dest, call, context, timeout, retries, rpcId,
00714                        rpcListener);
00715     } else {
00716         return sendRouteRpcCall(getThisCompType(), dest, call, context,
00717                          DEFAULT_ROUTING, timeout, retries, rpcId,
00718                          rpcListener);
00719     }
00720 }
00721 
00722