• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

daemon/src/net/DiscoveryAnnouncement.cpp

Go to the documentation of this file.
00001 /*
00002  * DiscoveryAnnouncement.cpp
00003  *
00004  *  Created on: 11.09.2009
00005  *      Author: morgenro
00006  */
00007 
00008 #include "net/DiscoveryAnnouncement.h"
00009 #include <ibrdtn/data/Exceptions.h>
00010 #include <ibrdtn/data/SDNV.h>
00011 #include <ibrcommon/Logger.h>
00012 #include <netinet/in.h>
00013 #include <typeinfo>
00014 #include <iostream>
00015 
00016 using namespace dtn::data;
00017 
00018 namespace dtn
00019 {
00020         namespace net
00021         {
00022                 DiscoveryAnnouncement::DiscoveryAnnouncement(const DiscoveryVersion version, dtn::data::EID eid)
00023                  : _version(version), _flags(BEACON_NO_FLAGS), _canonical_eid(eid)
00024                 {
00025                 }
00026 
00027                 DiscoveryAnnouncement::~DiscoveryAnnouncement()
00028                 {
00029                 }
00030 
00031                 bool DiscoveryAnnouncement::isShort()
00032                 {
00033                         switch (_version)
00034                         {
00035                         case DISCO_VERSION_00:
00036                                 return (_flags & DiscoveryAnnouncement::BEACON_SHORT);
00037 
00038                         case DISCO_VERSION_01:
00039                                 return !(_flags & DiscoveryAnnouncement::BEACON_SERVICE_BLOCK);
00040                         };
00041 
00042                         return false;
00043                 }
00044 
00045                 dtn::data::EID DiscoveryAnnouncement::getEID() const
00046                 {
00047                         return _canonical_eid;
00048                 }
00049 
00050                 const list<DiscoveryService> DiscoveryAnnouncement::getServices() const
00051                 {
00052                         return _services;
00053                 }
00054 
00055                 void DiscoveryAnnouncement::clearServices()
00056                 {
00057                         _services.clear();
00058                 }
00059 
00060                 const DiscoveryService& DiscoveryAnnouncement::getService(string name) const
00061                 {
00062                         for (std::list<DiscoveryService>::const_iterator iter = _services.begin(); iter != _services.end(); iter++)
00063                         {
00064                                 if ((*iter).getName() == name)
00065                                 {
00066                                         return (*iter);
00067                                 }
00068                         }
00069 
00070                         throw dtn::MissingObjectException("No service found with tag " + name);
00071                 }
00072 
00073                 void DiscoveryAnnouncement::addService(DiscoveryService service)
00074                 {
00075                         _services.push_back(service);
00076                 }
00077 
00078                 void DiscoveryAnnouncement::setSequencenumber(u_int16_t sequence)
00079                 {
00080                         _sn = sequence;
00081                 }
00082 
00083                 std::ostream &operator<<(std::ostream &stream, const DiscoveryAnnouncement &announcement)
00084                 {
00085                         const list<DiscoveryService> &services = announcement._services;
00086 
00087                         switch (announcement._version)
00088                         {
00089                                 case DiscoveryAnnouncement::DISCO_VERSION_00:
00090                                 {
00091                                         if (services.empty())
00092                                         {
00093                                                 unsigned char flags = DiscoveryAnnouncement::BEACON_SHORT | announcement._flags;
00094                                                 stream << (unsigned char)DiscoveryAnnouncement::DISCO_VERSION_00 << flags;
00095                                                 return stream;
00096                                         }
00097 
00098                                         dtn::data::BundleString eid(announcement._canonical_eid.getString());
00099                                         dtn::data::SDNV beacon_len;
00100 
00101                                         // determine the beacon length
00102                                         beacon_len += eid.getLength();
00103 
00104                                         // add service block length
00105                                         for (list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); iter++)
00106                                         {
00107                                                 beacon_len += (*iter).getLength();
00108                                         }
00109 
00110                                         stream << (unsigned char)DiscoveryAnnouncement::DISCO_VERSION_00 << announcement._flags << beacon_len << eid;
00111 
00112                                         for (list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); iter++)
00113                                         {
00114                                                 stream << (*iter);
00115                                         }
00116 
00117                                         break;
00118                                 }
00119 
00120                                 case DiscoveryAnnouncement::DISCO_VERSION_01:
00121                                 {
00122                                         unsigned char flags = 0;
00123 
00124                                         stream << (unsigned char)DiscoveryAnnouncement::DISCO_VERSION_01;
00125 
00126                                         if (announcement._canonical_eid != EID())
00127                                         {
00128                                                 flags |= DiscoveryAnnouncement::BEACON_CONTAINS_EID;
00129                                         }
00130 
00131                                         if (!services.empty())
00132                                         {
00133                                                 flags |= DiscoveryAnnouncement::BEACON_SERVICE_BLOCK;
00134                                         }
00135 
00136                                         stream << flags;
00137 
00138                                         // sequencenumber
00139                                         u_int16_t sn = htons(announcement._sn);
00140                                         stream.write( (char*)&sn, 2 );
00141 
00142                                         if ( flags && DiscoveryAnnouncement::BEACON_CONTAINS_EID )
00143                                         {
00144                                                 dtn::data::BundleString eid(announcement._canonical_eid.getString());
00145                                                 stream << eid;
00146                                         }
00147 
00148                                         if ( flags && DiscoveryAnnouncement::BEACON_SERVICE_BLOCK )
00149                                         {
00150                                                 stream << dtn::data::SDNV(services.size());
00151 
00152                                                 for (list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); iter++)
00153                                                 {
00154                                                         stream << (*iter);
00155                                                 }
00156                                         }
00157 
00158                                         break;
00159                                 }
00160 
00161                                 case DiscoveryAnnouncement::DTND_IPDISCOVERY:
00162                                 {
00163                                         char zero = '\0';
00164                                         u_int8_t interval = 10;
00165                                         // u_int32_t inet_addr;
00166                                         u_int16_t inet_port = htons(4556);
00167                                         std::string eid = announcement._canonical_eid.getString();
00168                                         u_int16_t eid_len = htons(eid.length());
00169                                         unsigned int add_zeros = (4 - (eid.length() % 4)) % 4;
00170                                         u_int16_t length = htons(12 + eid.length() + add_zeros);
00171 
00172 
00173                                         stream << (unsigned char)DiscoveryAnnouncement::DTND_IPDISCOVERY;
00174                                         stream.write((char*)&interval, 1);
00175                                         stream.write((char*)&length, 2);
00176 
00177 //                                      std::list<dtn::daemon::Configuration::NetConfig> interfaces = dtn::daemon::Configuration::getInstance().getInterfaces();
00178 //                                      dtn::daemon::Configuration::NetConfig &i = interfaces.front();
00179 
00180 //                                      struct sockaddr_in sock_address;
00181 //
00182 //                                      // set the local interface address
00183 //                                      i.interface.getAddress(&sock_address.sin_addr);
00184 //
00185 //                                      stream.write((char*)&sock_address.sin_addr, 4);
00186                                         stream.write(&zero, 1);
00187                                         stream.write(&zero, 1);
00188                                         stream.write(&zero, 1);
00189                                         stream.write(&zero, 1);
00190 
00191                                         stream.write((char*)&inet_port, 2);
00192                                         stream.write((char*)&eid_len, 2);
00193                                         stream << eid;
00194 
00195                                         for (unsigned int i = 0; i < add_zeros; i++)
00196                                         {
00197                                                 stream.write((char*)&zero, 1);
00198                                         }
00199 
00200                                         break;
00201                                 }
00202                         }
00203 
00204                         return stream;
00205                 }
00206 
00207                 std::istream &operator>>(std::istream &stream, DiscoveryAnnouncement &announcement)
00208                 {
00209                         unsigned char version = stream.get();
00210 
00211                         // do we running DTN2 compatibility mode?
00212                         if (announcement._version == DiscoveryAnnouncement::DTND_IPDISCOVERY)
00213                         {
00214                                 // read disco messages with version 1 as IPDiscovery (DTN2)
00215                                 if (version == DiscoveryAnnouncement::DISCO_VERSION_00)
00216                                 {
00217                                         version = DiscoveryAnnouncement::DTND_IPDISCOVERY;
00218                                 }
00219                         }
00220 
00221                         switch (version)
00222                         {
00223                         case DiscoveryAnnouncement::DISCO_VERSION_00:
00224                         {
00225                                 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 1 received" << IBRCOMMON_LOGGER_ENDL;
00226 
00227                                 dtn::data::SDNV beacon_len;
00228                                 dtn::data::SDNV eid_len;
00229 
00230                                 stream.get((char&)announcement._flags);
00231 
00232                                 // catch a short beacon
00233                                 if (DiscoveryAnnouncement::BEACON_SHORT == announcement._flags)
00234                                 {
00235                                         announcement._canonical_eid = dtn::data::EID();
00236                                         return stream;
00237                                 }
00238 
00239                                 stream >> beacon_len; int remain = beacon_len.getValue();
00240 
00241                                 dtn::data::BundleString eid;
00242                                 stream >> eid; remain -= eid.getLength();
00243                                 announcement._canonical_eid = dtn::data::EID((std::string)eid);
00244 
00245                                 // get the services
00246                                 list<DiscoveryService> &services = announcement._services;
00247 
00248                                 // clear the services
00249                                 services.clear();
00250 
00251                                 while (remain > 0)
00252                                 {
00253                                         // decode the service blocks
00254                                         DiscoveryService service;
00255                                         stream >> service;
00256                                         services.push_back(service);
00257                                         remain -= service.getLength();
00258                                 }
00259                                 break;
00260                         }
00261 
00262                         case DiscoveryAnnouncement::DISCO_VERSION_01:
00263                         {
00264                                 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 2 received" << IBRCOMMON_LOGGER_ENDL;
00265 
00266                                 stream.get((char&)announcement._flags);
00267 
00268                                 IBRCOMMON_LOGGER_DEBUG(25) << "beacon flags: " << hex << (int)announcement._flags << IBRCOMMON_LOGGER_ENDL;
00269 
00270                                 u_int16_t sn = 0;
00271                                 stream.read((char*)&sn, 2);
00272 
00273                                 // convert from network byte order
00274                                 u_int16_t sequencenumber = ntohs(sn);
00275 
00276                                 IBRCOMMON_LOGGER_DEBUG(25) << "beacon sequence number: " << sequencenumber << IBRCOMMON_LOGGER_ENDL;
00277 
00278                                 if (announcement._flags & DiscoveryAnnouncement::BEACON_CONTAINS_EID)
00279                                 {
00280                                         dtn::data::BundleString eid;
00281                                         stream >> eid;
00282 
00283                                         announcement._canonical_eid = dtn::data::EID((std::string)eid);
00284 
00285                                         IBRCOMMON_LOGGER_DEBUG(25) << "beacon eid: " << (std::string)eid << IBRCOMMON_LOGGER_ENDL;
00286                                 }
00287 
00288                                 if (announcement._flags & DiscoveryAnnouncement::BEACON_SERVICE_BLOCK)
00289                                 {
00290                                         // get the services
00291                                         list<DiscoveryService> &services = announcement._services;
00292 
00293                                         // read the number of services
00294                                         dtn::data::SDNV num_services;
00295                                         stream >> num_services;
00296 
00297                                         IBRCOMMON_LOGGER_DEBUG(25) << "beacon services (" << num_services.getValue() << "): " << IBRCOMMON_LOGGER_ENDL;
00298 
00299                                         // clear the services
00300                                         services.clear();
00301 
00302                                         for (unsigned int i = 0; i < num_services.getValue(); i++)
00303                                         {
00304                                                 // decode the service blocks
00305                                                 DiscoveryService service;
00306                                                 stream >> service;
00307                                                 services.push_back(service);
00308 
00309                                                 IBRCOMMON_LOGGER_DEBUG(25) << "\t " << service.getName() << " [" << service.getParameters() << "]" << IBRCOMMON_LOGGER_ENDL;
00310                                         }
00311                                 }
00312 
00313                                 if (announcement._flags & DiscoveryAnnouncement::BEACON_BLOOMFILTER)
00314                                 {
00315                                         // TODO: read the bloomfilter
00316                                 }
00317 
00318                                 break;
00319                         }
00320 
00321                         case DiscoveryAnnouncement::DTND_IPDISCOVERY:
00322                         {
00323                                 u_int8_t interval;
00324                                 u_int16_t length;
00325                                 u_int32_t inet_addr;
00326                                 u_int16_t inet_port;
00327                                 u_int16_t eid_len;
00328 
00329                                 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 0 received" << IBRCOMMON_LOGGER_ENDL;
00330 
00331                                 stream.read((char*)&interval, 1);
00332                                 stream.read((char*)&length, 2);
00333                                 stream.read((char*)&inet_addr, 4);
00334                                 stream.read((char*)&inet_port, 2);
00335                                 stream.read((char*)&eid_len, 2);
00336 
00337                                 char eid[eid_len];
00338                                 stream.read((char*)&eid, eid_len);
00339 
00340                                 announcement._version = DiscoveryAnnouncement::DTND_IPDISCOVERY;
00341                                 announcement._canonical_eid = EID(std::string(eid));
00342 
00343                                 break;
00344                         }
00345 
00346                         default:
00347                                 IBRCOMMON_LOGGER_DEBUG(20) << "unknown beacon received" << IBRCOMMON_LOGGER_ENDL;
00348 
00349                                 // Error, throw Exception!
00350                                 throw InvalidProtocolException("The received data does not match the discovery protocol.");
00351 
00352                                 break;
00353                         }
00354 
00355                         return stream;
00356                 }
00357 
00358                 string DiscoveryAnnouncement::toString() const
00359                 {
00360                         stringstream ss;
00361                         ss << "ANNOUNCE: " << _canonical_eid.getString();
00362                         return ss.str();
00363                 }
00364         }
00365 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1