ChannelAccess.cc

00001 /***************************************************************************
00002  * file:        ChannelAccess.cc
00003  *
00004  * author:      Marc Loebbers
00005  *
00006 
00007  * copyright:   (C) 2004 Telecommunication Networks Group (TKN) at
00008  *              Technische Universitaet Berlin, Germany.
00009  *
00010  *              This program is free software; you can redistribute it
00011  *              and/or modify it under the terms of the GNU General Public
00012  *              License as published by the Free Software Foundation; either
00013  *              version 2 of the License, or (at your option) any later
00014  *              version.
00015  *              For further information see file COPYING
00016  *              in the top level directory
00017  ***************************************************************************
00018  * part of:     framework implementation developed by tkn
00019  * description: - Base class for physical layers
00020  *              - if you create your own physical layer, please subclass
00021  *                from this class and use the sendToChannel() function!!
00022  ***************************************************************************
00023  * changelog:   $Revision: 284 $
00024  *              last modified:   $Date: 2006-06-07 16:55:24 +0200 (Mi, 07 Jun 2006) $
00025  *              by:              $Author: willkomm $
00026  **************************************************************************/
00027 
00028 
00029 #include "ChannelAccess.h"
00030 
00031 #include "Move.h"
00032 
00033 #include <cassert>
00034 
00035 BaseConnectionManager* ChannelAccess::getConnectionManager(cModule* nic)
00036 {
00037   std::string cmName = nic->hasPar("connectionManagerName")
00038              ? nic->par("connectionManagerName").stringValue()
00039              : "";
00040   if (cmName != ""){
00041     cModule* ccModule = simulation.getModuleByPath(cmName.c_str());
00042 
00043     return dynamic_cast<BaseConnectionManager *>(ccModule);
00044   }
00045   else {
00046     return FindModule<BaseConnectionManager *>::findGlobalModule();
00047   }
00048 }
00049 
00050 void ChannelAccess::initialize( int stage )
00051 {
00052   BatteryAccess::initialize(stage);
00053 
00054     if( stage == 0 ){
00055         hasPar("coreDebug") ? coreDebug = par("coreDebug").boolValue() : coreDebug = false;
00056 
00057         cModule* nic = getParentModule();
00058     cc = getConnectionManager(nic);
00059 
00060         if( cc == 0 ) error("Could not find connectionmanager module");
00061         // subscribe to position changes
00062         catMove = utility->subscribe(this, &move, findHost()->getId());
00063         isRegistered = false;
00064     }
00065 
00066     usePropagationDelay = par("usePropagationDelay");
00067 }
00068 
00069 
00070 
00071 void ChannelAccess::sendToChannel(cPacket *msg)
00072 {
00073     const NicEntry::GateList& gateList = cc->getGateList( getParentModule()->getId());
00074     NicEntry::GateList::const_iterator i = gateList.begin();
00075 
00076     if(useSendDirect){
00077         // use Andras stuff
00078         if( i != gateList.end() ){
00079           simtime_t delay = 0;
00080             for(; i != --gateList.end(); ++i){
00081               //calculate delay (Propagation) to this receiving nic
00082               delay = calculatePropagationDelay(i->first);
00083 
00084                 int radioStart = i->second->getId();
00085                 int radioEnd = radioStart + i->second->size();
00086                 for (int g = radioStart; g != radioEnd; ++g)
00087                     sendDirect(static_cast<cPacket*>(msg->dup()),
00088                                delay, msg->getDuration(), i->second->getOwnerModule(), g);
00089             }
00090             //calculate delay (Propagation) to this receiving nic
00091       delay = calculatePropagationDelay(i->first);
00092 
00093             int radioStart = i->second->getId();
00094             int radioEnd = radioStart + i->second->size();
00095             for (int g = radioStart; g != --radioEnd; ++g)
00096                 sendDirect(static_cast<cPacket*>(msg->dup()),
00097                            delay, msg->getDuration(), i->second->getOwnerModule(), g);
00098 
00099             sendDirect(msg, delay, msg->getDuration(), i->second->getOwnerModule(), radioEnd);
00100         }
00101         else{
00102             coreEV << "Nic is not connected to any gates!" << endl;
00103             delete msg;
00104         }
00105     }
00106     else{
00107         // use our stuff
00108         coreEV <<"sendToChannel: sending to gates\n";
00109         if( i != gateList.end() ){
00110           simtime_t delay = 0;
00111             for(; i != --gateList.end(); ++i){
00112               //calculate delay (Propagation) to this receiving nic
00113         delay = calculatePropagationDelay(i->first);
00114 
00115                 sendDelayed( static_cast<cPacket*>(msg->dup()),
00116                              delay, i->second );
00117             }
00118             //calculate delay (Propagation) to this receiving nic
00119       delay = calculatePropagationDelay(i->first);
00120 
00121             sendDelayed( msg, delay, i->second );
00122         }
00123         else{
00124             coreEV << "Nic is not connected to any gates!" << endl;
00125             delete msg;
00126         }
00127     }
00128 }
00129 
00130 
00131 void ChannelAccess::receiveBBItem(int category, const BBItem *details, int scopeModuleId)
00132 {
00133   BatteryAccess::receiveBBItem(category, details, scopeModuleId);
00134 
00135     if(category == catMove)
00136     {
00137         Move m(*static_cast<const Move*>(details));
00138 
00139         if(isRegistered) {
00140             cc->updateNicPos(getParentModule()->getId(), &m.getStartPos());
00141         }
00142         else {
00143             // register the nic with ConnectionManager
00144             // returns true, if sendDirect is used
00145             useSendDirect = cc->registerNic(getParentModule(), this, &m.getStartPos());
00146             isRegistered = true;
00147         }
00148         move = m;
00149         coreEV<<"new HostMove: "<<move.info()<<endl;
00150     }
00151 }
00152 
00153 simtime_t ChannelAccess::calculatePropagationDelay(const NicEntry* nic) {
00154   if(!usePropagationDelay)
00155     return 0;
00156 
00157   //receiver host move
00158   const Move& recvPos = nic->chAccess->move;
00159 
00160   // this is the time point when the transmission starts
00161   simtime_t actualTime = simTime();
00162 
00163   // this time-point is used to calculate the distance between sending and receiving host
00164   double distance = move.getPositionAt(actualTime).distance(recvPos.getPositionAt(actualTime));
00165 
00166   simtime_t delay = distance / BaseWorldUtility::speedOfLight;
00167   return delay;
00168 }
00169 
00170