EpidemicApp.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 "EpidemicApp.h"
00032 #include "EpidemicStore.h"
00033 
00034 #include "simlpy/interpreter_hooks.h"
00035 #include "pydtn/parsers.h"
00036 #include <iostream>
00037 
00038 using namespace Epidemic;
00039 
00040 DTN::ByteString EpidemicApp::kIdentifier((unsigned char*)"epidemic");
00041 unsigned char EpidemicApp::kSummaryVector = 0;
00042 unsigned char EpidemicApp::kDataRequest = 1;
00043 
00044 EpidemicApp::EpidemicApp( EpidemicStore* es,
00045                           DTN::Link* l,
00046                           const struct timeval& t ) :
00047    m_store( es ),
00048    m_link( l )
00049 {
00050    m_lifetime.tv_sec = t.tv_sec;
00051    m_lifetime.tv_usec = t.tv_usec;
00052 }
00053 
00054 EpidemicApp::~EpidemicApp()
00055 {
00056    LinkMap::iterator itr = m_linkMap.begin();
00057    LinkMap::iterator end = m_linkMap.end();
00058    for ( ; itr != end ; ++itr )
00059    {
00060       if ( 0 != itr->second )
00061       {
00062          delete itr->second;
00063       }
00064    }
00065 }
00066 
00067 void
00068 EpidemicApp::newNeighbor( const DTN::ByteString& addr )
00069 {
00070    if ( 0 == m_store ) return;
00071    if ( 0 == m_owner ) return;
00072 
00073    // Make sure there's a mock link for this address.
00074    if ( m_linkMap.end() == m_linkMap.find(addr) )
00075    {
00076       m_linkMap[addr] = new Mobility::MockLink(m_link,addr);
00077    }
00078 
00079    // First, find the last-hop-only bundles for the new neighbor and
00080    // enqueue them.
00081    m_store->forwardLastHop( addr, *m_owner );
00082 
00083    // Second, send the summary vector.
00084    DTN::ByteString* sv = m_store->summaryVector();
00085    if ( 0 == sv ) return;
00086    if ( 0 == sv->length() )
00087    {
00088       delete sv;
00089       return;
00090    }
00091    DTN::ByteString data;
00092    data.push_back( kSummaryVector );
00093    data.append( *sv );
00094    if ( verbosity() > 1 )
00095    {
00096       std::cout << "sending summary vector from "
00097                 << stringify(m_owner->addr())
00098                 << " to "
00099                 << stringify(addr)
00100                 << " ["
00101                 << stringify(*sv)
00102                 << "]"
00103                 << std::endl;
00104    }
00105    delete sv;
00106    struct timeval now = DTN::dtn_time();
00107    struct timeval exp = DTN::dtn_time();
00108    exp.tv_sec += m_lifetime.tv_sec;
00109    exp.tv_usec += m_lifetime.tv_usec;
00110    while ( exp.tv_usec > 1000000 )
00111    {
00112       exp.tv_usec -= 1000000;
00113       exp.tv_sec += 1;
00114    }
00115    DTN::Bundle* b = new DTN::Bundle( m_owner->nextSeq(),
00116                                      m_owner->addr(),
00117                                      addr,
00118                                      data,
00119                                      now,
00120                                      exp,
00121                                      DTN::Bundle::kData,
00122                                      appID() );
00123    // We have to set the receiver now.
00124    b->recv() = addr;
00125    m_owner->forward(b);
00126 }
00127 
00128 void
00129 EpidemicApp::process( const DTN::Bundle& b )
00130 {
00131    if ( 0 == m_store ) return;
00132 
00133    if ( b.payload().length() < 2 ) return;
00134 
00135    // If we've received a summary vector, look through it for
00136    // bundles we haven't seen and send a data request.
00137    if ( kSummaryVector == b.payload()[0] )
00138    {
00139       if ( verbosity() > 1 )
00140       {
00141          std::cout << "processing a summary vector at "
00142                    << stringify( m_owner->addr())
00143                    << " from "
00144                    << stringify( b.source() )
00145                    << std::endl;
00146       }
00147       EpidemicStore::DigestList* dl =
00148          EpidemicStore::parseSummaryVector( b.payload().substr(1) );
00149       if ( 0 == dl ) return;
00150       DTN::ByteString data;
00151       data.push_back( kDataRequest );
00152       EpidemicStore::DigestList::iterator itr = dl->begin();
00153       EpidemicStore::DigestList::iterator end = dl->end();
00154       bool haveReq = false;
00155       for ( ; itr != end ; ++itr )
00156       {
00157          if ( ! m_store->seen(*itr) )
00158          {
00159             haveReq = true;
00160             data.append( *itr );
00161          }
00162       }
00163       delete dl;
00164       if ( ! haveReq ) return;
00165       if ( verbosity() > 1 )
00166       {
00167          std::cout << "sending data request from "
00168                    << stringify(m_owner->addr())
00169                    << " to "
00170                    << stringify(b.source())
00171                    << " ["
00172                    << stringify(data)
00173                    << "]"
00174                    << std::endl;
00175       }
00176 
00177       struct timeval now = DTN::dtn_time();
00178       struct timeval exp = DTN::dtn_time();
00179       exp.tv_sec += m_lifetime.tv_sec;
00180       exp.tv_usec += m_lifetime.tv_usec;
00181       while ( exp.tv_usec > 1000000 )
00182       {
00183          exp.tv_usec -= 1000000;
00184          exp.tv_sec += 1;
00185       }
00186 
00187       DTN::Bundle* pB = new DTN::Bundle( m_owner->nextSeq(),
00188                                          m_owner->addr(),
00189                                          b.source(),
00190                                          data,
00191                                          now,
00192                                          exp,
00193                                          DTN::Bundle::kData,
00194                                          appID() );
00195       // We have to set the receiver now.
00196       pB->recv() = b.source();
00197       m_owner->forward(pB);
00198       return;
00199    }
00200 
00201    // If we've received a data request, enqueue the specified bundles.
00202    if ( kDataRequest == b.payload()[0] )
00203    {
00204       EpidemicStore::DigestList* dl =
00205          EpidemicStore::parseSummaryVector( b.payload().substr(1) );
00206       if ( 0 == dl ) return;
00207 
00208       EpidemicStore::DigestList::iterator itr = dl->begin();
00209       EpidemicStore::DigestList::iterator end = dl->end();
00210       for ( ; itr != end ; ++itr )
00211       {
00212          DTN::BundlePointer bp = m_store->getPointer(*itr);
00213          if ( ! bp.isNull() )
00214          {
00215             // Copy the bundle.
00216             DTN::Bundle* pB = bp.repr()->bundle()->clone();
00217             // Set the next-hop receiver to the requesting node.
00218             pB->recv() = b.source();
00219             // Enqueue the bundle.
00220             m_owner->forward(pB);
00221          }
00222       }
00223       delete dl;
00224 
00225       return;
00226    }
00227 
00228    // The message type was invalid.  We'll ignore this.
00229 }
00230 
00231 DTN::Link*
00232 EpidemicApp::getLink( const DTN::ByteString& addr )
00233 {
00234    LinkMap::iterator itr = m_linkMap.find(addr);
00235    if ( m_linkMap.end() == itr ) return 0;
00236    return itr->second;
00237 }

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