AgentXcpp  Revision:4ac4848
Internals Documentation
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends
/home/tanjeff/projekte/agentxcpp/src/oid.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2011 Tanjeff-Nicolai Moos <tanjeff@cccmz.de>
00003  *
00004  * This file is part of the agentXcpp library.
00005  *
00006  * AgentXcpp is free software: you can redistribute it and/or modify
00007  * it under the terms of the AgentXcpp library license, version 1, which 
00008  * consists of the GNU General Public License and some additional 
00009  * permissions.
00010  *
00011  * AgentXcpp is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * See the AgentXcpp library license in the LICENSE file of this package 
00017  * for more details.
00018  */
00019 
00020 //#include <iostream>
00021 #include "oid.hpp"
00022 #include "exceptions.hpp"
00023 
00024 
00025 using namespace agentxcpp;
00026 
00027 
00028 oid::oid(uint32_t  c1, uint32_t  c2, uint32_t  c3,
00029          uint32_t  c4, uint32_t  c5, uint32_t  c6,
00030          uint32_t  c7, uint32_t  c8, uint32_t  c9,
00031          uint32_t c10, uint32_t c11, uint32_t c12,
00032          uint32_t c13, uint32_t c14, uint32_t c15,
00033          uint32_t c16, uint32_t c17, uint32_t c18,
00034          uint32_t c19, uint32_t c20)
00035 {
00036     include = false;
00037 
00038     if(c1) push_back(c1); else return;
00039     if(c2) push_back(c2); else return;
00040     if(c3) push_back(c3); else return;
00041     if(c4) push_back(c4); else return;
00042     if(c5) push_back(c5); else return;
00043     if(c6) push_back(c6); else return;
00044     if(c7) push_back(c7); else return;
00045     if(c8) push_back(c8); else return;
00046     if(c9) push_back(c9); else return;
00047     
00048     if(c10) push_back(c10); else return;
00049     if(c11) push_back(c11); else return;
00050     if(c12) push_back(c12); else return;
00051     if(c13) push_back(c13); else return;
00052     if(c14) push_back(c14); else return;
00053     if(c15) push_back(c15); else return;
00054     if(c16) push_back(c16); else return;
00055     if(c17) push_back(c17); else return;
00056     if(c18) push_back(c18); else return;
00057     if(c19) push_back(c19); else return;
00058     
00059     if(c20) push_back(c20); else return;
00060 }
00061 
00062 
00063 oid::oid(const oid& o,
00064          uint32_t c1, uint32_t c2, uint32_t c3, uint32_t c4, uint32_t c5,
00065          uint32_t c6, uint32_t c7, uint32_t c8, uint32_t c9, uint32_t c10,
00066          uint32_t c11, uint32_t c12, uint32_t c13, uint32_t c14, uint32_t c15,
00067          uint32_t c16, uint32_t c17, uint32_t c18, uint32_t c19)
00068 {
00069     // start with o
00070     *this = o;
00071 
00072     if(c1) push_back(c1); else return;
00073     if(c2) push_back(c2); else return;
00074     if(c3) push_back(c3); else return;
00075     if(c4) push_back(c4); else return;
00076     if(c5) push_back(c5); else return;
00077     if(c6) push_back(c6); else return;
00078     if(c7) push_back(c7); else return;
00079     if(c8) push_back(c8); else return;
00080     if(c9) push_back(c9); else return;
00081     
00082     if(c10) push_back(c10); else return;
00083     if(c11) push_back(c11); else return;
00084     if(c12) push_back(c12); else return;
00085     if(c13) push_back(c13); else return;
00086     if(c14) push_back(c14); else return;
00087     if(c15) push_back(c15); else return;
00088     if(c16) push_back(c16); else return;
00089     if(c17) push_back(c17); else return;
00090     if(c18) push_back(c18); else return;
00091     if(c19) push_back(c19); else return;
00092 }
00093 
00094 
00095 std::ostream& agentxcpp::operator<<(std::ostream& out, const oid& o)
00096 {
00097     // Leading dot
00098     out << ".";
00099 
00100     // If no subidentifiers are present, we are done
00101     if(o.size() == 0)
00102     {
00103         return out;
00104     }
00105 
00106     // Get iterator to first subidentifier
00107     oid::const_iterator it = o.begin();
00108 
00109     // Print first subidentifier
00110     out << *it;
00111     it++;
00112 
00113     // Output remaining subidentifiers, each prepended with a dot
00114     while(it != o.end())
00115     {
00116         out << "." << *it;
00117         it++;
00118     }
00119 
00120     // Done, return
00121     return out;
00122 }
00123 
00124 
00125 
00126 data_t oid::serialize() const
00127 {
00128     // The serial representation of an OID is as follows (RFC 2741, section 
00129     // 5.1):
00130     //
00131     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00132     // |  n_subid      |  prefix       |  include      |  <reserved>   |
00133     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00134     // |                       sub-identifier #1                       |
00135     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00136     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00137     // |                       sub-identifier #n_subid                 |
00138     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00139     //
00140     // We use a string here to represent the serial stream, an we use some 
00141     // constants as indexes:
00142     const int n_subid_idx = 0;
00143     const int prefix_idx = 1;
00144     const int include_idx = 2;
00145     const int reserved_idx = 2;
00146 
00147     // This is our binary data:
00148     data_t serialized;
00149     serialized.resize(4);       // we will need at least the header
00150 
00151     // Set reserved field to 0
00152     serialized[reserved_idx] = 0;
00153 
00154     // Set include field
00155     serialized[include_idx] = include ? 1 : 0;
00156 
00157     // Iterator for the subid's
00158     oid::const_iterator subid = this->begin();
00159 
00160     // Check whether we can use the prefix (RFC 2741, section 5.1)
00161     if( this->size() >= 5 &&
00162         (*this)[0] == 1 &&
00163         (*this)[1] == 3 &&
00164         (*this)[2] == 6 &&
00165         (*this)[3] == 1 &&
00166         (*this)[4] <= 0xff)     // we have only one byte for the prefix!
00167     {
00168         // store the first integer after 1.3.6.1 to prefix field
00169         serialized[prefix_idx] = (*this)[4];
00170         subid += 5; // point to the subid behind prefix
00171 
00172         // 5 elements are represented by prefix
00173         serialized[n_subid_idx] = this->size() - 5;
00174     }
00175     else
00176     {
00177         // don't use prefix field
00178         serialized[prefix_idx] = 0;
00179 
00180         // All subid's are stored in the stream explicitly
00181         serialized[n_subid_idx] = this->size();
00182     }
00183 
00184     // copy subids to serialized
00185     while( subid != this->end() )
00186     {
00187         serialized.push_back( (*subid) << 24 & 0xff );
00188         serialized.push_back( (*subid) << 16 & 0xff );
00189         serialized.push_back( (*subid) << 8 & 0xff );
00190         serialized.push_back( (*subid) << 0 & 0xff );
00191         subid++;
00192     }
00193 
00194     return serialized;
00195 }
00196 
00197 oid::oid(data_t::const_iterator& pos,
00198          const data_t::const_iterator& end,
00199          bool big_endian)
00200 {
00201     if(end - pos < 4)
00202     {
00203         throw(parse_error());
00204     }
00205     
00206     // get number of subid's
00207     int n_subid = *pos++;
00208 
00209     // parse prefix
00210     int prefix = *pos++;
00211     if( prefix != 0 )
00212     {
00213         this->push_back(1);
00214         this->push_back(3);
00215         this->push_back(6);
00216         this->push_back(1);
00217         this->push_back(prefix);
00218     }
00219 
00220     // parse include field
00221     switch( *pos++ )
00222     {
00223         case 0:
00224             include = false;
00225             break;
00226         case 1:
00227             include = true;
00228             break;
00229         default:
00230             // Invalid value; we are picky and indicate an error:
00231             throw parse_error();
00232     }
00233 
00234     // skip reserved field
00235     *pos++;
00236 
00237     // parse rest of data, subid by subid
00238     if(end - pos < n_subid * 4)
00239     {
00240         throw(parse_error());
00241     }
00242     uint32_t subid;
00243     for( int i = 0; i < n_subid; i++)
00244     {
00245         if(big_endian)
00246         {
00247             // big endian
00248             subid =  *pos++ << 24;
00249             subid |= *pos++ << 16;
00250             subid |= *pos++ << 8;
00251             subid |= *pos++ << 0;
00252         }
00253         else
00254         {
00255             // little posdian
00256             subid =  *pos++ << 0;
00257             subid |= *pos++ << 8;
00258             subid |= *pos++ << 16;
00259             subid |= *pos++ << 24;
00260         }
00261         this->push_back(subid);
00262     }
00263 }
00264 
00265 
00266 bool oid::operator<(const oid& o) const
00267 {
00268     oid::const_iterator mine, yours;
00269     mine = this->begin();
00270     yours = o.begin();
00271 
00272     // Test as many parts as the shorter OID has:
00273     while( mine != this->end()
00274             && yours != o.end() )
00275     {
00276         if( *mine < *yours )
00277         {
00278             // my oid part is less than yours
00279             return true;
00280         }
00281         if( *mine > *yours )
00282         {
00283             // my oid part is greater than yours
00284             return false;
00285         }
00286 
00287         // our parts are identical; test next part:
00288         mine++;
00289         yours++;
00290     }
00291 
00292     // Ok, either you and I have different length (where the one with fewer 
00293     // parts is less than the other) or we have the same number of parts (in 
00294     // which case we are identical).
00295     if( this->size() < o.size() )
00296     {
00297         // I have less parts than you, so I am less than you:
00298         return true;
00299     }
00300     else
00301     {
00302         // I have not less parts than you:
00303         return false;
00304     }
00305 }
00306 
00307 
00308 
00309 bool oid::operator==(const oid& o) const
00310 {
00311     // Quick test: if the oids have different number of parts, they are not 
00312     // equal:
00313     if( this->size() != o.size() )
00314     {
00315         return false;
00316     }
00317     
00318     // Test all parts:
00319     oid::const_iterator mine, yours;
00320     mine = this->begin();
00321     yours = o.begin();
00322 
00323     while( mine != this->end()
00324             && yours != o.end() )
00325     {
00326         if( *mine != *yours )
00327         {
00328             // The parts differ: OIDs not equal
00329             return false;
00330         }
00331 
00332         // Parts are equal, test next parts
00333         mine++;
00334         yours++;
00335     }
00336 
00337     // All parts tested and all parts were equal. Further both OIDs have the 
00338     // same number of parts, thus they are equal.
00339     return true;
00340 }
00341 
00342 
00343 oid& oid::operator=(const oid& other)
00344 {
00345     // copy our own members
00346     this->include = other.include;
00347 
00348     // copy inherited stuff
00349     vector<uint32_t>::operator=(other);
00350     variable::operator=(other);
00351     
00352     // Return reference to us
00353     return *this;
00354 }