Go to the documentation of this file.00001
00002
00003
00004
00005
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
00102 beacon_len += eid.getLength();
00103
00104
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
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
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
00178
00179
00180
00181
00182
00183
00184
00185
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
00212 if (announcement._version == DiscoveryAnnouncement::DTND_IPDISCOVERY)
00213 {
00214
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
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
00246 list<DiscoveryService> &services = announcement._services;
00247
00248
00249 services.clear();
00250
00251 while (remain > 0)
00252 {
00253
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
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
00291 list<DiscoveryService> &services = announcement._services;
00292
00293
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
00300 services.clear();
00301
00302 for (unsigned int i = 0; i < num_services.getValue(); i++)
00303 {
00304
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
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
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 }