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