Header.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 "Header.h"
00032 #include "Exception.h"
00033 #include <netinet/in.h>
00034 
00035 using namespace DTN;
00036 
00037 //============================================
00038 // SDNV --- Self-delimiting numerical values
00039 //============================================
00040 
00041 SDNV::SDNV( const ByteString& s )
00042 {
00043    m_val.clear();
00044    const unsigned char mask = 0x80;
00045    ByteString::const_iterator itr = s.begin();
00046    ByteString::const_iterator end = s.end();
00047    for ( ; itr != end ; ++itr )
00048    {
00049       m_val += *itr;
00050       // if the first bit isn't set, this *must* be the last byte
00051       if ( !( mask & *itr ) ) break;
00052    }
00053 }
00054 
00055 SDNV&
00056 SDNV::operator=( const SDNV& v )
00057 {
00058    if ( this != &v )
00059    {
00060       m_val = v.val();
00061    }
00062    return *this;
00063 }
00064 
00065 SDNV::operator uint64_t() const
00066 {
00067    uint64_t l = 0;
00068    const unsigned char mask = 0x7F;
00069    ByteString::const_iterator itr = m_val.begin();
00070    ByteString::const_iterator end = m_val.end();
00071    for ( unsigned char n = 0 ; itr != end ; ++itr, ++n )
00072    {
00073       unsigned char temp = mask & *itr;
00074       unsigned char avail_bits = 8*sizeof(l) - 7*n;
00075       if ( (temp>>1) >= (1U<<(avail_bits-1)) )
00076       {
00077          throw Exception( __FILE__ , __LINE__ );
00078       }
00079       l <<= 7;
00080       l += (mask & *itr);
00081    }
00082    return l;
00083 }
00084 
00085 void
00086 SDNV::assign( uint64_t l )
00087 {
00088    const unsigned char mask = 0x7F;
00089    if ( m_val.size() != 0 )
00090    {
00091       m_val.clear();
00092    }
00093    while ( 0 != l )
00094    {
00095       unsigned char temp = l & mask;
00096       if ( ! m_val.empty() )
00097       {
00098          temp |= 0x80;
00099       }
00100       m_val.insert(0,1,temp);
00101       l >>= 7;
00102    }
00103 }
00104 
00105 
00106 //========================================
00107 // Header --- Base class for DTN headers
00108 //========================================
00109 
00110 Header::Header()
00111 {
00112 }
00113 
00114 Header::Header( const ByteString& hdr ) :
00115    m_data( hdr )
00116 {
00117 }
00118 
00119 Header::Header( const Header& hdr ) :
00120    m_data( hdr.m_data )
00121 {
00122 }
00123 
00124 Header::~Header()
00125 {
00126 }
00127 
00128 
00129 //=============================================================
00130 // PrimaryHeader --- Basic forwarding information header type
00131 //=============================================================
00132 
00133 PrimaryHeader::PrimaryHeader() :
00134    m_parsed ( false ),
00135    m_destinationSchemeOffset ( 0 ),
00136    m_destinationSSPOffset( 0 ),
00137    m_sourceSchemeOffset( 0 ),
00138    m_sourceSSPOffset( 0 ),
00139    m_reportToSchemeOffset( 0 ),
00140    m_reportToSSPOffset( 0 ),
00141    m_custodianSchemeOffset( 0 ),
00142    m_custodianSSPOffset( 0 ),
00143    m_creationTime( 0 ),
00144    m_creationSeqNum( 0 ),
00145    m_lifetime( 0 )
00146 {
00147 }
00148 
00149 PrimaryHeader::PrimaryHeader( const ByteString& hdr ) :
00150    Header( hdr ),
00151    m_parsed ( false ),
00152    m_destinationSchemeOffset ( 0 ),
00153    m_destinationSSPOffset( 0 ),
00154    m_sourceSchemeOffset( 0 ),
00155    m_sourceSSPOffset( 0 ),
00156    m_reportToSchemeOffset( 0 ),
00157    m_reportToSSPOffset( 0 ),
00158    m_custodianSchemeOffset( 0 ),
00159    m_custodianSSPOffset( 0 ),
00160    m_creationTime( 0 ),
00161    m_creationSeqNum( 0 ),
00162    m_lifetime( 0 )
00163 {
00164 }
00165 
00166 PrimaryHeader::PrimaryHeader( const PrimaryHeader& hdr ) :
00167    Header( hdr ),
00168    m_parsed ( false ),
00169    m_destinationSchemeOffset ( 0 ),
00170    m_destinationSSPOffset( 0 ),
00171    m_sourceSchemeOffset( 0 ),
00172    m_sourceSSPOffset( 0 ),
00173    m_reportToSchemeOffset( 0 ),
00174    m_reportToSSPOffset( 0 ),
00175    m_custodianSchemeOffset( 0 ),
00176    m_custodianSSPOffset( 0 ),
00177    m_creationTime( 0 ),
00178    m_creationSeqNum( 0 ),
00179    m_lifetime( 0 )
00180 {
00181 }
00182 
00183 PrimaryHeader::~PrimaryHeader()
00184 {
00185 }
00186 
00187 uint16_t
00188 PrimaryHeader::stringToShort( ByteString::size_type offset ) const
00189 {
00190    if ( m_data.length() < (offset+2) ) throw Exception( __FILE__ , __LINE__ );
00191    union { unsigned char c[2]; uint16_t s; } temp;
00192    temp.c[0] = m_data[offset];
00193    temp.c[1] = m_data[offset+1];
00194    return ntohs(temp.s);
00195 }
00196 
00197 uint32_t
00198 PrimaryHeader::stringToInt( ByteString::size_type offset ) const
00199 {
00200    if ( m_data.length() < (offset+4) ) throw Exception( __FILE__ , __LINE__ );
00201    union { unsigned char c[4]; uint32_t l; } temp;
00202    temp.c[0] = m_data[offset];
00203    temp.c[1] = m_data[offset+1];
00204    temp.c[2] = m_data[offset+2];
00205    temp.c[3] = m_data[offset+3];
00206    return ntohl(temp.l);
00207 }
00208 
00209 unsigned char
00210 PrimaryHeader::version() const
00211 {
00212    if ( m_data.length() < 1 ) throw Exception( __FILE__ , __LINE__ );
00213    return m_data[0];
00214 }
00215 
00216 unsigned char
00217 PrimaryHeader::flags() const
00218 {
00219    if ( m_data.length() < 2 ) throw Exception( __FILE__ , __LINE__ );
00220    return m_data[1];
00221 }
00222 
00223 unsigned char
00224 PrimaryHeader::COS() const
00225 {
00226    if ( m_data.length() < 3 ) throw Exception( __FILE__ , __LINE__ );
00227    return m_data[2];
00228 }
00229 
00230 unsigned char
00231 PrimaryHeader::SRR() const
00232 {
00233    if ( m_data.length() < 4 ) throw Exception( __FILE__ , __LINE__ );
00234    return m_data[3];
00235 }
00236 
00237 void
00238 PrimaryHeader::parse() const
00239 {
00240    // We take advantage of a bit of magic here.  Namely, m_data[] will
00241    // throw if the index is invalid.  This allows us to be cavalier
00242    // about checking.
00243 
00244    ByteString::size_type offset = 4;
00245    ByteString temp;
00246 
00247    do
00248    {
00249       temp += m_data[offset++];
00250    } while ( temp[temp.length()-1] & 0x80 );
00251    m_length = temp;
00252 
00253    m_destinationSchemeOffset = stringToShort( offset ); offset += 2;
00254    m_destinationSSPOffset = stringToShort( offset ); offset += 2;
00255    m_sourceSchemeOffset = stringToShort( offset ); offset += 2;
00256    m_sourceSSPOffset = stringToShort( offset ); offset += 2;
00257    m_reportToSchemeOffset = stringToShort( offset ); offset += 2;
00258    m_reportToSSPOffset = stringToShort( offset ); offset += 2;
00259    m_custodianSchemeOffset = stringToShort( offset ); offset += 2;
00260    m_custodianSSPOffset = stringToShort( offset ); offset += 2;
00261 
00262    m_creationTime = stringToInt( offset ); offset += 4;
00263    m_creationSeqNum = stringToInt( offset ); offset += 4;
00264    m_lifetime = stringToInt( offset ); offset += 4;
00265 
00266    temp.clear();
00267    do
00268    {
00269       temp += m_data[offset++];
00270    } while ( temp[temp.length()-1] & 0x80 );
00271    m_dictionaryLength = temp;
00272 
00273    ByteString::size_type end = offset + m_dictionaryLength;
00274    for ( ; offset < end ; ++offset )
00275    {
00276       m_dictionary += m_data[offset];
00277    }
00278 
00279    temp.clear();
00280    do
00281    {
00282       temp += m_data[offset++];
00283    } while ( temp[temp.length()-1] & 0x80 );
00284    m_fragmentOffset = temp;
00285 
00286    temp.clear();
00287    do
00288    {
00289       temp += m_data[offset++];
00290    } while ( temp[temp.length()-1] & 0x80 );
00291    m_applicationDataUnitLength = temp;
00292 
00293    m_parsed = true;
00294 }
00295 
00296 const SDNV&
00297 PrimaryHeader::length() const
00298 {
00299    if ( ! m_parsed ) parse();
00300    return m_length;
00301 }
00302 
00303 uint16_t
00304 PrimaryHeader::destinationSchemeOffset() const
00305 {
00306    if ( ! m_parsed ) parse();
00307    return m_destinationSchemeOffset;
00308 }
00309 
00310 uint16_t
00311 PrimaryHeader::destinationSSPOffset() const
00312 {
00313    if ( ! m_parsed ) parse();
00314    return m_destinationSSPOffset;
00315 }
00316 
00317 uint16_t
00318 PrimaryHeader::sourceSchemeOffset() const
00319 {
00320    if ( ! m_parsed ) parse();
00321    return m_sourceSchemeOffset;
00322 }
00323 
00324 uint16_t
00325 PrimaryHeader::sourceSSPOffset() const
00326 {
00327    if ( ! m_parsed ) parse();
00328    return m_sourceSSPOffset;
00329 }
00330 
00331 uint16_t
00332 PrimaryHeader::reportToSchemeOffset() const
00333 {
00334    if ( ! m_parsed ) parse();
00335    return m_reportToSchemeOffset;
00336 }
00337 
00338 uint16_t
00339 PrimaryHeader::reportToSSPOffset() const
00340 {
00341    if ( ! m_parsed ) parse();
00342    return m_reportToSSPOffset;
00343 }
00344 
00345 uint16_t
00346 PrimaryHeader::custodianSchemeOffset() const
00347 {
00348    if ( ! m_parsed ) parse();
00349    return m_custodianSchemeOffset;
00350 }
00351 
00352 uint16_t
00353 PrimaryHeader::custodianSSPOffset() const
00354 {
00355    if ( ! m_parsed ) parse();
00356    return m_custodianSSPOffset;
00357 }
00358 
00359 uint32_t
00360 PrimaryHeader::creationTime() const
00361 {
00362    if ( ! m_parsed ) parse();
00363    return m_creationTime;
00364 }
00365 
00366 uint32_t
00367 PrimaryHeader::creationSeqNum() const
00368 {
00369    if ( ! m_parsed ) parse();
00370    return m_creationSeqNum;
00371 }
00372 
00373 uint32_t
00374 PrimaryHeader::lifetime() const
00375 {
00376    if ( ! m_parsed ) parse();
00377    return m_lifetime;
00378 }
00379 
00380 const SDNV&
00381 PrimaryHeader::dictionaryLength() const
00382 {
00383    if ( ! m_parsed ) parse();
00384    return m_dictionaryLength;
00385 }
00386 
00387 const ByteString&
00388 PrimaryHeader::dictionary() const
00389 {
00390    if ( ! m_parsed ) parse();
00391    return m_dictionary;
00392 }
00393 
00394 const SDNV&
00395 PrimaryHeader::fragmentOffset() const
00396 {
00397    if ( ! m_parsed ) parse();
00398    return m_fragmentOffset;
00399 }
00400 
00401 const SDNV&
00402 PrimaryHeader::applicationDataUnitLength() const
00403 {
00404    if ( ! m_parsed ) parse();
00405    return m_applicationDataUnitLength;
00406 }
00407 
00408 
00409 //==========================================================
00410 // RegularHeader --- Base type for non-primary DTN headers
00411 //==========================================================
00412 
00413 RegularHeader::RegularHeader()
00414 {
00415 }
00416 
00417 RegularHeader::RegularHeader( const ByteString& hdr ) :
00418    Header( hdr )
00419 {
00420 }
00421 
00422 RegularHeader::RegularHeader( const RegularHeader& hdr ) :
00423    Header( hdr )
00424 {
00425 }
00426 
00427 RegularHeader::~RegularHeader()
00428 {
00429 }
00430 
00431 unsigned char
00432 RegularHeader::typeCode() const
00433 {
00434    if ( 0 == m_data.length() )
00435    {
00436       throw Exception( __FILE__ , __LINE__ );
00437    }
00438    return m_data[0];
00439 }
00440 
00441 unsigned char
00442 RegularHeader::flags() const
00443 {
00444    if ( m_data.length() < 2 )
00445    {
00446       throw Exception( __FILE__ , __LINE__ );
00447    }
00448    return m_data[1];
00449 }
00450 
00451 SDNV
00452 RegularHeader::length() const
00453 {
00454    ByteString s;
00455    for ( unsigned int i = 2; i < m_data.length() ; ++i )
00456    {
00457       s += m_data[i];
00458       if ( !(0x80 & m_data[i]) ) // the high bit is 0
00459       {
00460          return s;
00461       }
00462    }
00463    throw Exception( __FILE__ , __LINE__ );
00464 }
00465 
00466 
00467 //============================================
00468 // PayloadHeader --- Data-holding DTN header
00469 //============================================
00470 
00471 PayloadHeader::PayloadHeader()
00472 {
00473 }
00474 
00475 PayloadHeader::PayloadHeader( const ByteString& pld, unsigned char flags )
00476 {
00477    m_data.clear();
00478    m_data += kPayloadHeader;
00479    m_data += flags;
00480    SDNV length = pld.length();
00481    m_data += length.val();
00482    m_data += pld;
00483 }
00484 
00485 PayloadHeader::PayloadHeader( const PayloadHeader& hdr ) :
00486    RegularHeader( hdr )
00487 {
00488 }
00489 
00490 PayloadHeader::~PayloadHeader()
00491 {
00492 }
00493 
00494 ByteString
00495 PayloadHeader::payload() const
00496 {
00497    return m_data.substr(m_offset);
00498 }

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