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 u_int8_t cl_type = 1;
00164 char zero = '\0';
00165 u_int8_t interval = 10;
00166
00167 u_int16_t inet_port = htons(4556);
00168 std::string eid = announcement._canonical_eid.getString();
00169 u_int16_t eid_len = htons(eid.length());
00170 unsigned int add_zeros = (4 - (eid.length() % 4)) % 4;
00171 u_int16_t length = htons(12 + eid.length() + add_zeros);
00172
00173
00174 stream << (unsigned char)cl_type;
00175 stream.write((char*)&interval, 1);
00176 stream.write((char*)&length, 2);
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 stream.write(&zero, 1);
00188 stream.write(&zero, 1);
00189 stream.write(&zero, 1);
00190 stream.write(&zero, 1);
00191
00192 stream.write((char*)&inet_port, 2);
00193 stream.write((char*)&eid_len, 2);
00194 stream << eid;
00195
00196 for (unsigned int i = 0; i < add_zeros; i++)
00197 {
00198 stream.write((char*)&zero, 1);
00199 }
00200
00201 break;
00202 }
00203 }
00204
00205 return stream;
00206 }
00207
00208 std::istream &operator>>(std::istream &stream, DiscoveryAnnouncement &announcement)
00209 {
00210 unsigned char version = 0;
00211
00212
00213 if (announcement._version == DiscoveryAnnouncement::DTND_IPDISCOVERY)
00214 {
00215
00216 version = DiscoveryAnnouncement::DTND_IPDISCOVERY;
00217 }
00218 else
00219 {
00220
00221 version = stream.get();
00222 }
00223
00224 switch (version)
00225 {
00226 case DiscoveryAnnouncement::DISCO_VERSION_00:
00227 {
00228 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 1 received" << IBRCOMMON_LOGGER_ENDL;
00229
00230 dtn::data::SDNV beacon_len;
00231 dtn::data::SDNV eid_len;
00232
00233 stream.get((char&)announcement._flags);
00234
00235
00236 if (DiscoveryAnnouncement::BEACON_SHORT == announcement._flags)
00237 {
00238 announcement._canonical_eid = dtn::data::EID();
00239 return stream;
00240 }
00241
00242 stream >> beacon_len; int remain = beacon_len.getValue();
00243
00244 dtn::data::BundleString eid;
00245 stream >> eid; remain -= eid.getLength();
00246 announcement._canonical_eid = dtn::data::EID((std::string)eid);
00247
00248
00249 list<DiscoveryService> &services = announcement._services;
00250
00251
00252 services.clear();
00253
00254 while (remain > 0)
00255 {
00256
00257 DiscoveryService service;
00258 stream >> service;
00259 services.push_back(service);
00260 remain -= service.getLength();
00261 }
00262 break;
00263 }
00264
00265 case DiscoveryAnnouncement::DISCO_VERSION_01:
00266 {
00267 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 2 received" << IBRCOMMON_LOGGER_ENDL;
00268
00269 stream.get((char&)announcement._flags);
00270
00271 IBRCOMMON_LOGGER_DEBUG(25) << "beacon flags: " << hex << (int)announcement._flags << IBRCOMMON_LOGGER_ENDL;
00272
00273 u_int16_t sn = 0;
00274 stream.read((char*)&sn, 2);
00275
00276
00277 u_int16_t sequencenumber = ntohs(sn);
00278
00279 IBRCOMMON_LOGGER_DEBUG(25) << "beacon sequence number: " << sequencenumber << IBRCOMMON_LOGGER_ENDL;
00280
00281 if (announcement._flags & DiscoveryAnnouncement::BEACON_CONTAINS_EID)
00282 {
00283 dtn::data::BundleString eid;
00284 stream >> eid;
00285
00286 announcement._canonical_eid = dtn::data::EID((std::string)eid);
00287
00288 IBRCOMMON_LOGGER_DEBUG(25) << "beacon eid: " << (std::string)eid << IBRCOMMON_LOGGER_ENDL;
00289 }
00290
00291 if (announcement._flags & DiscoveryAnnouncement::BEACON_SERVICE_BLOCK)
00292 {
00293
00294 list<DiscoveryService> &services = announcement._services;
00295
00296
00297 dtn::data::SDNV num_services;
00298 stream >> num_services;
00299
00300 IBRCOMMON_LOGGER_DEBUG(25) << "beacon services (" << num_services.getValue() << "): " << IBRCOMMON_LOGGER_ENDL;
00301
00302
00303 services.clear();
00304
00305 for (unsigned int i = 0; i < num_services.getValue(); i++)
00306 {
00307
00308 DiscoveryService service;
00309 stream >> service;
00310 services.push_back(service);
00311
00312 IBRCOMMON_LOGGER_DEBUG(25) << "\t " << service.getName() << " [" << service.getParameters() << "]" << IBRCOMMON_LOGGER_ENDL;
00313 }
00314 }
00315
00316 if (announcement._flags & DiscoveryAnnouncement::BEACON_BLOOMFILTER)
00317 {
00318
00319 }
00320
00321 break;
00322 }
00323
00324 case DiscoveryAnnouncement::DTND_IPDISCOVERY:
00325 {
00326 u_int8_t cl_type;
00327 u_int8_t interval;
00328 u_int16_t length;
00329 u_int32_t inet_addr;
00330 u_int16_t inet_port;
00331 u_int16_t eid_len;
00332
00333 IBRCOMMON_LOGGER_DEBUG(15) << "beacon IPDiscovery (DTN2) frame received" << IBRCOMMON_LOGGER_ENDL;
00334
00335 stream.read((char*)&cl_type, 1);
00336 stream.read((char*)&interval, 1);
00337 stream.read((char*)&length, 2);
00338 stream.read((char*)&inet_addr, 4);
00339 stream.read((char*)&inet_port, 2);
00340 stream.read((char*)&eid_len, 2);
00341
00342 char eid[eid_len];
00343 stream.read((char*)&eid, eid_len);
00344
00345 announcement._version = DiscoveryAnnouncement::DTND_IPDISCOVERY;
00346 announcement._canonical_eid = EID(std::string(eid));
00347
00348 break;
00349 }
00350
00351 default:
00352 IBRCOMMON_LOGGER_DEBUG(20) << "unknown beacon received" << IBRCOMMON_LOGGER_ENDL;
00353
00354
00355 throw InvalidProtocolException("The received data does not match the discovery protocol.");
00356
00357 break;
00358 }
00359
00360 return stream;
00361 }
00362
00363 string DiscoveryAnnouncement::toString() const
00364 {
00365 stringstream ss;
00366 ss << "ANNOUNCE: " << _canonical_eid.getString();
00367 return ss.str();
00368 }
00369 }
00370 }