RFLink.cc

00001 // Copyright 2008 Michael Marsh, University of Maryland.
00002 //
00003 // This file is part of pydtn.
00004 //
00005 // pydtn is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // pydtn is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // The views and conclusions contained in the software and documentation
00019 // are those of the authors and should not be interpreted as representing
00020 // official policies, either expressed or implied, of the University
00021 // of Maryland.
00022 //
00023 // pydtn extends and embeds the Python interpreter, which is
00024 // Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025 // and is released under the PSF License Agreement.
00026 //
00027 // RANLUX random number generation uses the Boost library,
00028 // Copyright 1994-2006 by various authors (details in individual files),
00029 // which is released under the Boost Software License, Version 1.0.
00030 
00031 #include "simlpy/interpreter_defs.h"
00032 #include "simlpy/interpreter_hooks.h"
00033 
00034 #include "RFLink.h"
00035 
00036 #include "pydtn/BundleEvent.h"
00037 #include "mobility/MobileNode.h"
00038 #include "simlpy/Clock.h"
00039 #include "simlpy/SimulationException.h"
00040 
00041 #include <math.h>
00042 #include <iostream>
00043 
00044 using namespace RF;
00045 
00046 RFLink::NodeList RFLink::listeners;
00047 
00048 RFLink::RFLink()
00049 {
00050 }
00051 
00052 RFLink::~RFLink()
00053 {
00054 }
00055 
00056 Entity*
00057 RFLink::create() const
00058 {
00059    return new RFLink;
00060 }
00061 
00062 void
00063 RFLink::configure( const ArgList& args )
00064 {
00065    unsigned int nargs = args.size();
00066    if ( 0 == nargs )
00067    {
00068       std::cerr << "no configuration options were passed" << std::endl;
00069       throw SimulationException( __FILE__ , __LINE__ );
00070    }
00071    std::string command = parse_string(args[0]);
00072    if ( "connect" == command )
00073    {
00074       // base class does the parsing
00075       WirelessLink::configure(args);
00076       if ( 0 != m_node )
00077       {
00078          listeners.push_back( m_node );
00079       }
00080       return;
00081    }
00082    if ( "range" == command )
00083    {
00084       if ( nargs < 2 )
00085       {
00086          std::cerr << "config('range') requires two arguments"
00087                    << std::endl;
00088          throw SimulationException( __FILE__ , __LINE__ );
00089       }
00090       m_range = parse_double(args[1]);
00091       return;
00092    }
00093    WirelessLink::configure(args);
00094 }
00095 
00096 InterpreterItem
00097 RFLink::get( const ArgList& args )
00098 {
00099    unsigned int nargs = args.size();
00100    if ( 0 == nargs )
00101    {
00102       std::cerr << "No attribute specified" << std::endl;
00103       throw SimulationException( __FILE__ , __LINE__ );
00104    }
00105 
00106    std::string attr = parse_string(args[0]);
00107 
00108    if ( "range" == attr )
00109    {
00110       return construct_double( m_range );
00111    }
00112    if ( "visible" == attr )
00113    {
00114       ArgList alist;
00115       Mobility::Position  pos = m_node->position();
00116       double rnorm = m_range * m_range;
00117       NodeList::iterator  itr = listeners.begin();
00118       NodeList::iterator  end = listeners.end();
00119       for ( ; itr != end ; ++itr )
00120       {
00121          // make sure it's not a NULL pointer
00122          if ( 0 == *itr ) continue;
00123 
00124          // we don't send messages to ourself
00125          if ( m_node == *itr ) continue;
00126 
00127          // compute the vector from us to the potential recipient
00128          Mobility::Position  rcvrPos = (*itr)->position() - pos;
00129 
00130          // quick rectangular comparisons
00131          if ( fabs( rcvrPos.x() ) > m_range ) continue;
00132          if ( fabs( rcvrPos.y() ) > m_range ) continue;
00133          if ( fabs( rcvrPos.z() ) > m_range ) continue;
00134 
00135          // we're within the cube, but what about the sphere?
00136          double norm = rcvrPos.x() * rcvrPos.x()
00137             + rcvrPos.y() * rcvrPos.y()
00138             + rcvrPos.z() * rcvrPos.z();
00139          if ( norm > rnorm ) continue;
00140 
00141          alist.push_back( construct_string( (*itr)->addrString() ) );
00142       }
00143 
00144       return construct_list(alist);
00145    }
00146 
00147    return WirelessLink::get(args);
00148 }
00149 
00150 bool
00151 RFLink::handler( BundleEvent& event )
00152 {
00153    bool sent = false;
00154 
00155    if ( m_link.up() )
00156    {
00157       if ( event.sentAt() >= m_link.upSince() )
00158       {
00159          Mobility::Position  pos = m_node->position();
00160          double rnorm = m_range * m_range;
00161          NodeList::iterator  itr = listeners.begin();
00162          NodeList::iterator  end = listeners.end();
00163          for ( ; itr != end ; ++itr )
00164          {
00165             // make sure it's not a NULL pointer
00166             if ( 0 == *itr ) continue;
00167 
00168             // we don't send messages to ourself
00169             if ( m_node == *itr ) continue;
00170 
00171             // compute the vector from us to the potential recipient
00172             Mobility::Position  rcvrPos = (*itr)->position() - pos;
00173 
00174             // quick rectangular comparisons
00175             if ( fabs( rcvrPos.x() ) > m_range ) continue;
00176             if ( fabs( rcvrPos.y() ) > m_range ) continue;
00177             if ( fabs( rcvrPos.z() ) > m_range ) continue;
00178 
00179             // we're within the cube, but what about the sphere?
00180             double norm = rcvrPos.x() * rcvrPos.x()
00181                + rcvrPos.y() * rcvrPos.y()
00182                + rcvrPos.z() * rcvrPos.z();
00183             if ( norm > rnorm ) continue;
00184 
00185             // everything checks out -- send this node the bundle
00186             DTN::Bundle* b = event.data().clone();
00187             Clock::schedule( new BundleEvent( this,
00188                                               *itr,
00189                                               event.sentAt(),
00190                                               Clock::time(),
00191                                               b ) );
00192             sent = true;
00193          }
00194       }
00195    }
00196 
00197    // If we get here, the Bundle is going to disappear.
00198    if ( 0 == m_source )
00199    {
00200       throw SimulationException( __FILE__ , __LINE__ );
00201    }
00202 
00203    // If the bundle was sent, the BundleEvent will still own its data,
00204    // and will clean it up when its destructor is invoked.
00205    return sent;
00206 }

Generated on Mon Mar 24 11:15:46 2008 for Pydtn Simulator by  doxygen 1.5.4