IBR-DTNSuite
0.8
|
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 u_int8_t cl_type = 1; 00164 char zero = '\0'; 00165 u_int8_t interval = 10; 00166 // u_int32_t inet_addr; 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 // std::list<dtn::daemon::Configuration::NetConfig> interfaces = dtn::daemon::Configuration::getInstance().getInterfaces(); 00179 // dtn::daemon::Configuration::NetConfig &i = interfaces.front(); 00180 00181 // struct sockaddr_in sock_address; 00182 // 00183 // // set the local interface address 00184 // i.interface.getAddress(&sock_address.sin_addr); 00185 // 00186 // stream.write((char*)&sock_address.sin_addr, 4); 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 // do we running DTN2 compatibility mode? 00213 if (announcement._version == DiscoveryAnnouncement::DTND_IPDISCOVERY) 00214 { 00215 // set version to IPDiscovery (DTN2) 00216 version = DiscoveryAnnouncement::DTND_IPDISCOVERY; 00217 } 00218 else 00219 { 00220 // read IPND version of the frame 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 // catch a short beacon 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 // get the services 00249 list<DiscoveryService> &services = announcement._services; 00250 00251 // clear the services 00252 services.clear(); 00253 00254 while (remain > 0) 00255 { 00256 // decode the service blocks 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 // convert from network byte order 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 // get the services 00294 list<DiscoveryService> &services = announcement._services; 00295 00296 // read the number of services 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 // clear the services 00303 services.clear(); 00304 00305 for (unsigned int i = 0; i < num_services.getValue(); i++) 00306 { 00307 // decode the service blocks 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 // TODO: read the bloomfilter 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 // Error, throw Exception! 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 }