00001 #ifndef ENDPOINT_SET_HPP_
00002 #define ENDPOINT_SET_HPP_
00003
00004 #include "addressing.hpp"
00005 #include "tcpip_endpoint.hpp"
00006
00007 #include <sstream>
00008 #include <boost/unordered_set.hpp>
00009 #include <boost/foreach.hpp>
00010 #include <boost/thread.hpp>
00011
00012 namespace ariba {
00013 namespace addressing {
00014
00015 using boost::unordered_set;
00016
00027 class endpoint_set {
00028 public:
00029
00030 unordered_set<mac_address> bluetooth;
00031
00032
00033 unordered_set<ip_address> ip;
00034
00035
00036 unordered_set<tcp_port_address> tcp;
00037 unordered_set<rfcomm_channel_address> rfcomm;
00038
00039
00040 boost::mutex io_mutex;
00041 typedef boost::mutex::scoped_lock scoped_lock;
00042
00043 private:
00044 template<uint8_t type, class V>
00045 size_t to_bytes_dynamic( const unordered_set<V>& set, uint8_t* bytes ) const {
00046 size_t size = 0;
00047 bytes[0] = type;
00048 uint8_t* size_ptr = bytes+1;
00049 bytes +=2;
00050 size += 2;
00051 BOOST_FOREACH( const V& value, set ) {
00052 bytes[0] = (uint8_t)value.to_bytes_size();
00053 bytes++;
00054 size++;
00055 value.to_bytes(bytes);
00056 bytes += value.to_bytes_size();
00057 size += value.to_bytes_size();
00058 }
00059 *size_ptr = size-2;
00060 return size;
00061 }
00062
00063 template<class V>
00064 void from_bytes_dynamic( unordered_set<V>& set, const uint8_t* bytes, uint8_t size ) {
00065 size_t pos = 0;
00066 while (pos < size) {
00067 uint8_t length = bytes[0];
00068 bytes++; pos++;
00069 V obj(bytes,length);
00070 set.insert(obj);
00071 bytes+=length; pos+=length;
00072 }
00073 }
00074
00075 template<uint8_t type, class V>
00076 size_t to_bytes_fixed( const unordered_set<V>& set, uint8_t* bytes ) const {
00077 size_t fixed_size = V().to_bytes_size();
00078 bytes[0] = type;
00079 bytes[1] = (uint8_t)(set.size()* fixed_size);
00080 bytes+=2;
00081 BOOST_FOREACH( const V& value, set ) {
00082 value.to_bytes(bytes);
00083 bytes += value.to_bytes_size();
00084 }
00085 return 2 + set.size() * fixed_size;
00086 }
00087
00088 template<class V>
00089 void from_bytes_fixed( unordered_set<V>& set, const uint8_t* bytes, uint8_t size ) {
00090 size_t fixed_size = V().to_bytes_size();
00091 uint8_t num = size/fixed_size;
00092 for (uint8_t i=0; i<num; i++) {
00093 V obj(bytes, fixed_size);
00094 set.insert(obj);
00095 bytes += fixed_size;
00096 }
00097 }
00098
00099 template<class V>
00100 std::string to_string_set( const unordered_set<V>& set, const std::string& type ) const {
00101 if (set.size()==0) return std::string("");
00102 std::ostringstream buf;
00103 buf << type << "{";
00104 bool first = true;
00105 BOOST_FOREACH( const V& value, set ) {
00106 if (!first) {
00107 buf << " | ";
00108 } else
00109 first = false;
00110 buf << value.to_string();
00111 }
00112 buf << "};";
00113 return buf.str();
00114 }
00115
00116 static void trim(string& str) {
00117 string::size_type pos = str.find_last_not_of(' ');
00118 if(pos != string::npos) {
00119 str.erase(pos + 1);
00120 pos = str.find_first_not_of(' ');
00121 if(pos != string::npos) str.erase(0, pos);
00122 }
00123 else str.erase(str.begin(), str.end());
00124 }
00125
00126 static string::size_type skip( const char* chars, string::size_type pos, const std::string& str ) {
00127 bool found = true;
00128 while (pos<str.size() && found) {
00129 found = false;
00130 for (size_t i=0; chars[i]!=0 && !found; i++)
00131 if (str.at(pos)==chars[i]) {
00132 pos++;
00133 found = true;
00134 }
00135 }
00136 return pos;
00137 }
00138
00139 template<class V>
00140 size_t from_string_set( unordered_set<V>& set, string::size_type pos, const std::string& str ) {
00141 while (pos < str.size() && pos != string::npos) {
00142 pos = skip("} |\n\r", pos, str);
00143 string::size_type nend1 = str.find('}',pos);
00144 string::size_type nend2 = str.find('|',pos);
00145 if (nend1==string::npos && nend2==string::npos) break;
00146 if (nend1==string::npos) nend1=str.size();
00147 if (nend2==string::npos) nend2=str.size();
00148 string::size_type nend = nend2 < nend1 ? nend2:nend1;
00149 std::string sub = str.substr(pos, min(nend2,nend1)-pos);
00150 trim(sub);
00151
00152 V obj( sub );
00153 set.insert(obj);
00154 pos = nend+1;
00155 if (nend1<nend2) break;
00156 }
00157 return pos-1;
00158 }
00159
00160 public:
00161 enum layers {
00162 Layer1 = 1, Layer2 = 2, Layer3 = 4, Layer4 = 8, Layer5 = 16,
00163 Layer6 = 32, Layer7 = 64, Layer8 = 128, AllLayers = ~0,
00164 Layer1_3 = Layer1|Layer2|Layer3,
00165 Layer1_4 = Layer1|Layer2|Layer3|Layer4,
00166 };
00167
00168 endpoint_set() {
00169
00170 }
00171
00172 endpoint_set( const endpoint_set& copy ) :
00173 bluetooth(copy.bluetooth), ip(copy.ip), tcp(copy.tcp), rfcomm(copy.rfcomm) {
00174 }
00175
00176 endpoint_set( const std::string& str ) {
00177 assign(str);
00178 }
00179
00180 endpoint_set( const uint8_t* bytes, size_t size ) {
00181 assign(bytes, size);
00182 }
00183
00185 void add( const address_v* address, int layers = AllLayers ) {
00186 scoped_lock lock(io_mutex);
00187 if ( address->instanceof<tcpip_endpoint> () ) {
00188 const tcpip_endpoint& addr = *address;
00189 if (layers & Layer3) ip.insert( addr.address() );
00190 if (layers & Layer4) tcp.insert( addr.port() );
00191 } else
00192 if ( address->instanceof<ip_address>() ) {
00193 const ip_address& addr = *address;
00194 if (layers & Layer3) ip.insert( addr );
00195 } else
00196 if (address->instanceof<rfcomm_endpoint>() ) {
00197 const rfcomm_endpoint& endp = *address;
00198 if (layers & Layer2) bluetooth.insert( endp.mac() );
00199 if (layers & Layer4) rfcomm.insert( endp.channel() );
00200 } else
00201 if (address->instanceof<mac_address>() ) {
00202 const mac_address& endp = *address;
00203 if (layers & Layer2) bluetooth.insert( endp );
00204 }
00205 }
00206
00208 void add( const endpoint_set& eps, int layers = AllLayers ) {
00209 scoped_lock lock(io_mutex);
00210
00211
00212 if (layers & Layer2) {
00213 bluetooth.insert(eps.bluetooth.begin(), eps.bluetooth.end() );
00214 }
00215
00216
00217 if (layers & Layer3) {
00218 ip.insert(eps.ip.begin(), eps.ip.end() );
00219 }
00220
00221
00222 if (layers & Layer4) {
00223 tcp.insert(eps.tcp.begin(), eps.tcp.end() );
00224 rfcomm.insert(eps.rfcomm.begin(), eps.rfcomm.end() );
00225 }
00226 }
00227
00229 void remove( const address_vf address ) {
00230 scoped_lock lock(io_mutex);
00231 if ( address->instanceof<tcpip_endpoint> () ) {
00232 const tcpip_endpoint& addr = *address;
00233 ip.erase( addr.address() );
00234 tcp.erase( addr.port() );
00235 } else
00236 if ( address->instanceof<ip_address>() ) {
00237 const ip_address& addr = *address;
00238 ip.erase( addr );
00239 } else
00240 if (address->instanceof<rfcomm_endpoint>() ) {
00241 const rfcomm_endpoint& endp = *address;
00242 bluetooth.erase( endp.mac() );
00243 rfcomm.erase( endp.channel() );
00244 }
00245 }
00246
00249 bool disjoint_to( const endpoint_set& set ) const {
00250 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00251 BOOST_FOREACH( const mac_address& mac, bluetooth )
00252 if (set.bluetooth.count(mac) !=0 ) return false;
00253 BOOST_FOREACH( const ip_address& ip_, ip )
00254 if (set.ip.count(ip_) !=0 ) return false;
00255 return true;
00256 }
00257
00258 bool intersects_with( const endpoint_set& set ) const {
00259 return !disjoint_to(set);
00260 }
00261
00262 bool is_subset_of( const endpoint_set& set ) const {
00263 throw "Not implemented!";
00264 return false;
00265 }
00266
00268 bool is_bytes_size_static() const {
00269 return false;
00270 }
00271
00273 size_t to_bytes_size() const {
00274 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00275 size_t size = 0;
00276
00277
00278 size += bluetooth.size() * mac_address().to_bytes_size();
00279
00280
00281 BOOST_FOREACH( const ip_address& ip_, ip )
00282 size += (ip_.to_bytes_size() + 1 );
00283
00284
00285 size += tcp.size() * tcp_port_address().to_bytes_size();
00286
00287
00288 size += rfcomm.size() * rfcomm_channel_address().to_bytes_size();
00289
00290
00291 size += 4 * 2 ;
00292
00293 return size;
00294 }
00295
00297 void to_bytes(uint8_t* bytes) const {
00298 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00299
00301 bytes += to_bytes_fixed<0x21, mac_address>( bluetooth, bytes );
00302
00303
00304 bytes += to_bytes_dynamic<0x31, ip_address>(ip, bytes);
00305
00306
00307 bytes += to_bytes_fixed<0x41, tcp_port_address>( tcp, bytes );
00308
00309
00310 bytes += to_bytes_fixed<0x42, rfcomm_channel_address>( rfcomm, bytes );
00311 }
00312
00314 bool assign(const uint8_t* bytes, size_t size) {
00315 scoped_lock lock(io_mutex);
00316
00317 size_t pos = 0;
00318 while (pos < size) {
00319 uint8_t type = bytes[0];
00320 uint8_t length = bytes[1];
00321 bytes+=2; pos+=2;
00322
00323 switch (type) {
00324
00325
00326 case 0x21: {
00327 from_bytes_fixed<mac_address>( bluetooth, bytes, length );
00328 break;
00329 }
00330
00331
00332 case 0x31: {
00333 from_bytes_dynamic<ip_address>( ip, bytes, length );
00334 break;
00335 }
00336
00337 case 0x41: {
00338 from_bytes_fixed<tcp_port_address>( tcp, bytes, length );
00339 break;
00340 }
00341
00342 case 0x42: {
00343 from_bytes_fixed<rfcomm_channel_address>( rfcomm, bytes, length );
00344 break;
00345 }
00346
00347 default: {
00348 pos = size;
00349 break;
00350 }
00351 }
00352 bytes += length; pos+=length;
00353 }
00354 return false;
00355 }
00356
00358 std::string to_string() const {
00359 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00360 std::string smac = to_string_set<mac_address>(bluetooth, "bluetooth");
00361 std::string sip = to_string_set<ip_address>(ip, "ip");
00362 std::string stcp = to_string_set<tcp_port_address>(tcp, "tcp");
00363 std::string srfcomm = to_string_set<rfcomm_channel_address>(rfcomm, "rfcomm");
00364 return smac+sip+stcp+srfcomm;
00365 }
00366
00368 void assign( const std::string& str ) {
00369 scoped_lock lock(io_mutex);
00370 string::size_type pos = 0;
00371 while (pos < str.size() && pos!=string::npos) {
00372 pos = skip("}; \n\r", pos, str );
00373 string::size_type nend = str.find('{',pos);
00374 if (nend == string::npos) break;
00375 std::string type = str.substr(pos,nend-pos);
00376 pos = nend+1;
00377 trim(type);
00378 if (type=="bluetooth")
00379 pos = from_string_set<mac_address>(bluetooth, pos, str );
00380 else if (type=="ip")
00381 pos = from_string_set<ip_address>(ip, pos, str );
00382 else if (type=="tcp")
00383 pos = from_string_set<tcp_port_address>(tcp, pos, str );
00384 else if (type=="rfcomm")
00385 pos = from_string_set<rfcomm_channel_address>(rfcomm, pos, str );
00386 else
00387 pos = str.find('}',pos);
00388 }
00389 }
00390
00391 endpoint_set& operator=( const endpoint_set& rhs ) {
00392 scoped_lock lock(io_mutex);
00393 this->bluetooth = rhs.bluetooth;
00394 this->ip = rhs.ip;
00395 this->rfcomm = rhs.rfcomm;
00396 this->tcp = rhs.tcp;
00397 }
00398
00400 bool operator== ( const endpoint_set& rhs ) const {
00401 return (rhs.rfcomm == rfcomm && rhs.ip == ip && rhs.tcp == tcp &&
00402 rhs.bluetooth == bluetooth);
00403 }
00404
00405 bool operator!= ( const endpoint_set& rhs ) const {
00406 return !(*this==rhs);
00407 }
00408 };
00409
00410 }}
00411
00412 #endif