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 dtn::data::EID DiscoveryAnnouncement::getEID() const 00032 { 00033 return _canonical_eid; 00034 } 00035 00036 const list<DiscoveryService> DiscoveryAnnouncement::getServices() const 00037 { 00038 return _services; 00039 } 00040 00041 void DiscoveryAnnouncement::clearServices() 00042 { 00043 _services.clear(); 00044 } 00045 00046 const DiscoveryService& DiscoveryAnnouncement::getService(string name) const 00047 { 00048 for (std::list<DiscoveryService>::const_iterator iter = _services.begin(); iter != _services.end(); iter++) 00049 { 00050 if ((*iter).getName() == name) 00051 { 00052 return (*iter); 00053 } 00054 } 00055 00056 throw dtn::MissingObjectException("No service found with tag " + name); 00057 } 00058 00059 void DiscoveryAnnouncement::addService(DiscoveryService service) 00060 { 00061 _services.push_back(service); 00062 } 00063 00064 void DiscoveryAnnouncement::setSequencenumber(u_int16_t sequence) 00065 { 00066 _sn = sequence; 00067 } 00068 00069 std::ostream &operator<<(std::ostream &stream, const DiscoveryAnnouncement &announcement) 00070 { 00071 const list<DiscoveryService> &services = announcement._services; 00072 00073 switch (announcement._version) 00074 { 00075 case DiscoveryAnnouncement::DISCO_VERSION_00: 00076 { 00077 if (services.empty()) 00078 { 00079 unsigned char flags = DiscoveryAnnouncement::BEACON_SHORT | announcement._flags; 00080 stream << (unsigned char)DiscoveryAnnouncement::DISCO_VERSION_00 << flags; 00081 return stream; 00082 } 00083 00084 dtn::data::BundleString eid(announcement._canonical_eid.getString()); 00085 dtn::data::SDNV beacon_len; 00086 00087 // determine the beacon length 00088 beacon_len += eid.getLength(); 00089 00090 // add service block length 00091 for (list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); iter++) 00092 { 00093 beacon_len += (*iter).getLength(); 00094 } 00095 00096 stream << (unsigned char)DiscoveryAnnouncement::DISCO_VERSION_00 << announcement._flags << beacon_len << eid; 00097 00098 for (list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); iter++) 00099 { 00100 stream << (*iter); 00101 } 00102 } 00103 00104 case DiscoveryAnnouncement::DISCO_VERSION_01: 00105 { 00106 unsigned char flags = 0; 00107 00108 stream << (unsigned char)DiscoveryAnnouncement::DISCO_VERSION_01; 00109 00110 if (announcement._canonical_eid != EID()) 00111 { 00112 flags |= DiscoveryAnnouncement::BEACON_CONTAINS_EID; 00113 } 00114 00115 if (!services.empty()) 00116 { 00117 flags |= DiscoveryAnnouncement::BEACON_SERVICE_BLOCK; 00118 } 00119 00120 stream << flags; 00121 00122 // sequencenumber 00123 u_int16_t sn = htons(announcement._sn); 00124 stream.write( (char*)&sn, 2 ); 00125 00126 if ( flags && DiscoveryAnnouncement::BEACON_CONTAINS_EID ) 00127 { 00128 dtn::data::BundleString eid(announcement._canonical_eid.getString()); 00129 stream << eid; 00130 } 00131 00132 if ( flags && DiscoveryAnnouncement::BEACON_SERVICE_BLOCK ) 00133 { 00134 stream << dtn::data::SDNV(services.size()); 00135 00136 for (list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); iter++) 00137 { 00138 stream << (*iter); 00139 } 00140 } 00141 } 00142 } 00143 00144 return stream; 00145 } 00146 00147 std::istream &operator>>(std::istream &stream, DiscoveryAnnouncement &announcement) 00148 { 00149 unsigned char version = stream.get(); 00150 00151 switch (version) 00152 { 00153 case DiscoveryAnnouncement::DISCO_VERSION_00: 00154 { 00155 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 1 received" << IBRCOMMON_LOGGER_ENDL; 00156 00157 dtn::data::SDNV beacon_len; 00158 dtn::data::SDNV eid_len; 00159 00160 stream.get((char&)announcement._flags); 00161 00162 // catch a short beacon 00163 if (DiscoveryAnnouncement::BEACON_SHORT == announcement._flags) 00164 { 00165 announcement._canonical_eid = dtn::data::EID(); 00166 return stream; 00167 } 00168 00169 stream >> beacon_len; int remain = beacon_len.getValue(); 00170 00171 dtn::data::BundleString eid; 00172 stream >> eid; remain -= eid.getLength(); 00173 announcement._canonical_eid = dtn::data::EID((std::string)eid); 00174 00175 // get the services 00176 list<DiscoveryService> &services = announcement._services; 00177 00178 // clear the services 00179 services.clear(); 00180 00181 while (remain > 0) 00182 { 00183 // decode the service blocks 00184 DiscoveryService service; 00185 stream >> service; 00186 services.push_back(service); 00187 remain -= service.getLength(); 00188 } 00189 break; 00190 } 00191 00192 case DiscoveryAnnouncement::DISCO_VERSION_01: 00193 { 00194 IBRCOMMON_LOGGER_DEBUG(15) << "beacon version 2 received" << IBRCOMMON_LOGGER_ENDL; 00195 00196 stream.get((char&)announcement._flags); 00197 00198 IBRCOMMON_LOGGER_DEBUG(25) << "beacon flags: " << hex << (int)announcement._flags << IBRCOMMON_LOGGER_ENDL; 00199 00200 u_int16_t sn = 0; 00201 stream.read((char*)&sn, 2); 00202 00203 // convert from network byte order 00204 u_int16_t sequencenumber = ntohs(sn); 00205 00206 IBRCOMMON_LOGGER_DEBUG(25) << "beacon sequence number: " << sequencenumber << IBRCOMMON_LOGGER_ENDL; 00207 00208 if (announcement._flags & DiscoveryAnnouncement::BEACON_CONTAINS_EID) 00209 { 00210 dtn::data::BundleString eid; 00211 stream >> eid; 00212 00213 announcement._canonical_eid = dtn::data::EID((std::string)eid); 00214 00215 IBRCOMMON_LOGGER_DEBUG(25) << "beacon eid: " << (std::string)eid << IBRCOMMON_LOGGER_ENDL; 00216 } 00217 00218 if (announcement._flags & DiscoveryAnnouncement::BEACON_SERVICE_BLOCK) 00219 { 00220 // get the services 00221 list<DiscoveryService> &services = announcement._services; 00222 00223 // read the number of services 00224 dtn::data::SDNV num_services; 00225 stream >> num_services; 00226 00227 IBRCOMMON_LOGGER_DEBUG(25) << "beacon services (" << num_services.getValue() << "): " << IBRCOMMON_LOGGER_ENDL; 00228 00229 // clear the services 00230 services.clear(); 00231 00232 for (unsigned int i = 0; i < num_services.getValue(); i++) 00233 { 00234 // decode the service blocks 00235 DiscoveryService service; 00236 stream >> service; 00237 services.push_back(service); 00238 00239 IBRCOMMON_LOGGER_DEBUG(25) << "\t " << service.getName() << " [" << service.getParameters() << "]" << IBRCOMMON_LOGGER_ENDL; 00240 } 00241 } 00242 00243 if (announcement._flags & DiscoveryAnnouncement::BEACON_BLOOMFILTER) 00244 { 00245 // TODO: read the bloomfilter 00246 } 00247 00248 break; 00249 } 00250 00251 default: 00252 IBRCOMMON_LOGGER_DEBUG(20) << "unknown beacon received" << IBRCOMMON_LOGGER_ENDL; 00253 00254 // Error, throw Exception! 00255 throw InvalidProtocolException("The received data does not match the discovery protocol."); 00256 00257 break; 00258 } 00259 00260 return stream; 00261 } 00262 00263 string DiscoveryAnnouncement::toString() const 00264 { 00265 stringstream ss; 00266 ss << "ANNOUNCE: " << _canonical_eid.getString(); 00267 return ss.str(); 00268 } 00269 } 00270 }
1.6.3