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, NoLoopback = 256,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 &&
00190 !((layers & NoLoopback) && addr.address().is_loopback()) )
00191 ip.insert( addr.address() );
00192 if (layers & Layer4) tcp.insert( addr.port() );
00193 } else
00194 if ( address->instanceof<ip_address>() ) {
00195 const ip_address& addr = *address;
00196 if ((layers & Layer3) &&
00197 !((layers & NoLoopback) && addr.is_loopback()))
00198 ip.insert( addr );
00199 } else
00200 if (address->instanceof<rfcomm_endpoint>() ) {
00201 const rfcomm_endpoint& endp = *address;
00202 if (layers & Layer2) bluetooth.insert( endp.mac() );
00203 if (layers & Layer4) rfcomm.insert( endp.channel() );
00204 } else
00205 if (address->instanceof<mac_address>() ) {
00206 const mac_address& endp = *address;
00207 if (layers & Layer2) bluetooth.insert( endp );
00208 }
00209 }
00210
00212 void add( const endpoint_set& eps, int layers = AllLayers ) {
00213 scoped_lock lock(io_mutex);
00214
00215
00216 if (layers & Layer2) {
00217 bluetooth.insert(eps.bluetooth.begin(), eps.bluetooth.end() );
00218 }
00219
00220
00221 if (layers & Layer3) {
00222 ip.insert(eps.ip.begin(), eps.ip.end() );
00223 }
00224
00225
00226 if (layers & Layer4) {
00227 tcp.insert(eps.tcp.begin(), eps.tcp.end() );
00228 rfcomm.insert(eps.rfcomm.begin(), eps.rfcomm.end() );
00229 }
00230 }
00231
00233 void remove( const address_vf address ) {
00234 scoped_lock lock(io_mutex);
00235 if ( address->instanceof<tcpip_endpoint> () ) {
00236 const tcpip_endpoint& addr = *address;
00237 ip.erase( addr.address() );
00238 tcp.erase( addr.port() );
00239 } else
00240 if ( address->instanceof<ip_address>() ) {
00241 const ip_address& addr = *address;
00242 ip.erase( addr );
00243 } else
00244 if (address->instanceof<rfcomm_endpoint>() ) {
00245 const rfcomm_endpoint& endp = *address;
00246 bluetooth.erase( endp.mac() );
00247 rfcomm.erase( endp.channel() );
00248 }
00249 }
00250
00253 bool disjoint_to( const endpoint_set& set ) const {
00254 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00255 BOOST_FOREACH( const mac_address& mac, bluetooth )
00256 if (set.bluetooth.count(mac) !=0 ) return false;
00257 BOOST_FOREACH( const ip_address& ip_, ip )
00258 if (set.ip.count(ip_) !=0 ) return false;
00259 return true;
00260 }
00261
00262 bool intersects_with( const endpoint_set& set ) const {
00263 return !disjoint_to(set);
00264 }
00265
00266 bool is_subset_of( const endpoint_set& set ) const {
00267 throw "Not implemented!";
00268 return false;
00269 }
00270
00272 bool is_bytes_size_static() const {
00273 return false;
00274 }
00275
00277 size_t to_bytes_size() const {
00278 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00279 size_t size = 0;
00280
00281
00282 size += bluetooth.size() * mac_address().to_bytes_size();
00283
00284
00285 BOOST_FOREACH( const ip_address& ip_, ip )
00286 size += (ip_.to_bytes_size() + 1 );
00287
00288
00289 size += tcp.size() * tcp_port_address().to_bytes_size();
00290
00291
00292 size += rfcomm.size() * rfcomm_channel_address().to_bytes_size();
00293
00294
00295 size += 4 * 2 ;
00296
00297 return size;
00298 }
00299
00301 void to_bytes(uint8_t* bytes) const {
00302 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00303
00305 bytes += to_bytes_fixed<0x21, mac_address>( bluetooth, bytes );
00306
00307
00308 bytes += to_bytes_dynamic<0x31, ip_address>(ip, bytes);
00309
00310
00311 bytes += to_bytes_fixed<0x41, tcp_port_address>( tcp, bytes );
00312
00313
00314 bytes += to_bytes_fixed<0x42, rfcomm_channel_address>( rfcomm, bytes );
00315 }
00316
00318 bool assign(const uint8_t* bytes, size_t size) {
00319 scoped_lock lock(io_mutex);
00320
00321 size_t pos = 0;
00322 while (pos < size) {
00323 uint8_t type = bytes[0];
00324 uint8_t length = bytes[1];
00325 bytes+=2; pos+=2;
00326
00327 switch (type) {
00328
00329
00330 case 0x21: {
00331 from_bytes_fixed<mac_address>( bluetooth, bytes, length );
00332 break;
00333 }
00334
00335
00336 case 0x31: {
00337 from_bytes_dynamic<ip_address>( ip, bytes, length );
00338 break;
00339 }
00340
00341 case 0x41: {
00342 from_bytes_fixed<tcp_port_address>( tcp, bytes, length );
00343 break;
00344 }
00345
00346 case 0x42: {
00347 from_bytes_fixed<rfcomm_channel_address>( rfcomm, bytes, length );
00348 break;
00349 }
00350
00351 default: {
00352 pos = size;
00353 break;
00354 }
00355 }
00356 bytes += length; pos+=length;
00357 }
00358 return false;
00359 }
00360
00362 std::string to_string() const {
00363 scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
00364 std::string smac = to_string_set<mac_address>(bluetooth, "bluetooth");
00365 std::string sip = to_string_set<ip_address>(ip, "ip");
00366 std::string stcp = to_string_set<tcp_port_address>(tcp, "tcp");
00367 std::string srfcomm = to_string_set<rfcomm_channel_address>(rfcomm, "rfcomm");
00368 return smac+sip+stcp+srfcomm;
00369 }
00370
00372 void assign( const std::string& str ) {
00373 scoped_lock lock(io_mutex);
00374 string::size_type pos = 0;
00375 while (pos < str.size() && pos!=string::npos) {
00376 pos = skip("}; \n\r", pos, str );
00377 string::size_type nend = str.find('{',pos);
00378 if (nend == string::npos) break;
00379 std::string type = str.substr(pos,nend-pos);
00380 pos = nend+1;
00381 trim(type);
00382 if (type=="bluetooth")
00383 pos = from_string_set<mac_address>(bluetooth, pos, str );
00384 else if (type=="ip")
00385 pos = from_string_set<ip_address>(ip, pos, str );
00386 else if (type=="tcp")
00387 pos = from_string_set<tcp_port_address>(tcp, pos, str );
00388 else if (type=="rfcomm")
00389 pos = from_string_set<rfcomm_channel_address>(rfcomm, pos, str );
00390 else
00391 pos = str.find('}',pos);
00392 }
00393 }
00394
00395 endpoint_set& operator=( const endpoint_set& rhs ) {
00396 scoped_lock lock(io_mutex);
00397 this->bluetooth = rhs.bluetooth;
00398 this->ip = rhs.ip;
00399 this->rfcomm = rhs.rfcomm;
00400 this->tcp = rhs.tcp;
00401 return *this;
00402 }
00403
00405 bool operator== ( const endpoint_set& rhs ) const {
00406 return (rhs.rfcomm == rfcomm && rhs.ip == ip && rhs.tcp == tcp &&
00407 rhs.bluetooth == bluetooth);
00408 }
00409
00410 bool operator!= ( const endpoint_set& rhs ) const {
00411 return !(*this==rhs);
00412 }
00413 };
00414
00415 }}
00416
00417 #endif