| 1 |
/* |
|---|
| 2 |
* Copyright (C) 2005 Andrea Leofreddi <andrea.leofreddi@libero.it> |
|---|
| 3 |
* |
|---|
| 4 |
* This program is free software; you can redistribute it and/or modify |
|---|
| 5 |
* it under the terms of the GNU General Public License as published by |
|---|
| 6 |
* the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 |
* (at your option) any later version. |
|---|
| 8 |
* |
|---|
| 9 |
* This program is distributed in the hope that it will be useful, |
|---|
| 10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 |
* GNU General Public License for more details. |
|---|
| 13 |
* |
|---|
| 14 |
* You should have received a copy of the GNU General Public License |
|---|
| 15 |
* along with this program; if not, write to the Free Software |
|---|
| 16 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 17 |
*/ |
|---|
| 18 |
|
|---|
| 19 |
/** |
|---|
| 20 |
* \file kademlia.h Generic Kademlia Implementation |
|---|
| 21 |
*/ |
|---|
| 22 |
|
|---|
| 23 |
#ifndef __KADEMLIA_H__ |
|---|
| 24 |
#define __KADEMLIA_H__ |
|---|
| 25 |
|
|---|
| 26 |
#include <list> |
|---|
| 27 |
#include <bitset> |
|---|
| 28 |
#include <iomanip> |
|---|
| 29 |
#include <stdexcept> |
|---|
| 30 |
#include <algorithm> |
|---|
| 31 |
#include <iterator> |
|---|
| 32 |
|
|---|
| 33 |
#include <hnbase/config.h> |
|---|
| 34 |
#include <hnbase/hash.h> |
|---|
| 35 |
#include <hnbase/ipv4addr.h> |
|---|
| 36 |
#include <hncore/modules.h> |
|---|
| 37 |
#include <hncore/kademlia_util.h> |
|---|
| 38 |
|
|---|
| 39 |
#include <boost/static_assert.hpp> |
|---|
| 40 |
|
|---|
| 41 |
/** |
|---|
| 42 |
* @page kad Generic Kademlia implementation, version 2 |
|---|
| 43 |
* |
|---|
| 44 |
* \section intro Introduction |
|---|
| 45 |
* Since Kademlia has been implemented in many different ways, this header |
|---|
| 46 |
* supplies a generic templatized version that allow user to gain some code |
|---|
| 47 |
* reuse. |
|---|
| 48 |
* |
|---|
| 49 |
* \section types Types |
|---|
| 50 |
* An Id an unique identification number that identifies both nodes and values. |
|---|
| 51 |
* Kademlia sheets assume a 160bit wide id, but some implementations use |
|---|
| 52 |
* a different number of bits: in this header, an Id is assumed to be a |
|---|
| 53 |
* std::bitset with the correct number of required bit. On top of Id, a |
|---|
| 54 |
* Kad::Contact is built: a Contact is a tuple containing a node Id, its ip |
|---|
| 55 |
* address and udp port. Kad::Contact is a template<int N>, where N is the |
|---|
| 56 |
* number of bits to use for id. Kad::Contact::IdType is defined as bitset<N>. |
|---|
| 57 |
* Implementations can inherit Kad::Contact to add data to each contact. |
|---|
| 58 |
* |
|---|
| 59 |
*/ |
|---|
| 60 |
|
|---|
| 61 |
/** |
|---|
| 62 |
* Generic Kademlia implementation |
|---|
| 63 |
*/ |
|---|
| 64 |
namespace Kad { |
|---|
| 65 |
|
|---|
| 66 |
/** |
|---|
| 67 |
* Generic messages |
|---|
| 68 |
*/ |
|---|
| 69 |
class Messages { |
|---|
| 70 |
enum __unnamed__ { |
|---|
| 71 |
PING, STORE, FIND_NODE, FIND_VALUE |
|---|
| 72 |
}; |
|---|
| 73 |
}; |
|---|
| 74 |
|
|---|
| 75 |
/** |
|---|
| 76 |
* Given a IdType, returns its prefix type in Typein Type. |
|---|
| 77 |
* Specializing this template to use custom prefixes |
|---|
| 78 |
*/ |
|---|
| 79 |
template<typename IdType> |
|---|
| 80 |
struct Prefix { |
|---|
| 81 |
typedef std::pair<IdType, unsigned> Type; |
|---|
| 82 |
}; |
|---|
| 83 |
|
|---|
| 84 |
/** |
|---|
| 85 |
* Assure bits after mask are set to 0 |
|---|
| 86 |
*/ |
|---|
| 87 |
template<typename IdType> |
|---|
| 88 |
void prefixCheck(const typename Kad::Prefix<IdType>::Type& p) { |
|---|
| 89 |
IdType t( |
|---|
| 90 |
Kad::KUtils::buildMask( |
|---|
| 91 |
p.second, |
|---|
| 92 |
Kad::KUtils::TypeToType<IdType>() |
|---|
| 93 |
) & p.first |
|---|
| 94 |
); |
|---|
| 95 |
|
|---|
| 96 |
CHECK_THROW(t == p.first); |
|---|
| 97 |
} |
|---|
| 98 |
|
|---|
| 99 |
/** |
|---|
| 100 |
* Compare two prefixes |
|---|
| 101 |
*/ |
|---|
| 102 |
template< |
|---|
| 103 |
typename IdType |
|---|
| 104 |
> |
|---|
| 105 |
struct PrefixLess { |
|---|
| 106 |
typedef typename Prefix<IdType>::Type PrefixType; |
|---|
| 107 |
|
|---|
| 108 |
bool operator()( |
|---|
| 109 |
const typename Kad::Prefix<IdType>::Type& t, |
|---|
| 110 |
const typename Kad::Prefix<IdType>::Type& u |
|---|
| 111 |
) const { |
|---|
| 112 |
prefixCheck<IdType>(t); |
|---|
| 113 |
prefixCheck<IdType>(u); |
|---|
| 114 |
|
|---|
| 115 |
return (t < u) || (t.first < u.first); |
|---|
| 116 |
} |
|---|
| 117 |
}; |
|---|
| 118 |
|
|---|
| 119 |
/** |
|---|
| 120 |
* IdBelongsToPrefix predicate checks if an id belongs to a |
|---|
| 121 |
* given prefix. |
|---|
| 122 |
* |
|---|
| 123 |
* @param IdType Type of id object |
|---|
| 124 |
*/ |
|---|
| 125 |
template< |
|---|
| 126 |
typename IdType |
|---|
| 127 |
> |
|---|
| 128 |
struct IdBelongsToPrefix { |
|---|
| 129 |
typedef typename Prefix<IdType>::Type PrefixType; |
|---|
| 130 |
|
|---|
| 131 |
typedef bool result_type; |
|---|
| 132 |
|
|---|
| 133 |
bool operator()(const IdType& id) const { |
|---|
| 134 |
return (id & m_mask) == m_prefix; |
|---|
| 135 |
} |
|---|
| 136 |
|
|---|
| 137 |
IdBelongsToPrefix(const PrefixType& prefix) |
|---|
| 138 |
: m_mask(KUtils::buildMask( |
|---|
| 139 |
prefix.second, |
|---|
| 140 |
KUtils::TypeToType<IdType>() |
|---|
| 141 |
)), m_prefix(prefix.first & m_mask) |
|---|
| 142 |
{ } |
|---|
| 143 |
|
|---|
| 144 |
private: |
|---|
| 145 |
IdType m_mask; |
|---|
| 146 |
IdType m_prefix; |
|---|
| 147 |
}; |
|---|
| 148 |
|
|---|
| 149 |
/** |
|---|
| 150 |
* PrefixContainsId predicate checks if a predicate contains a |
|---|
| 151 |
* given id. |
|---|
| 152 |
* |
|---|
| 153 |
* @param IdType Type of id object |
|---|
| 154 |
*/ |
|---|
| 155 |
template< |
|---|
| 156 |
typename IdType |
|---|
| 157 |
> |
|---|
| 158 |
struct PrefixContainsId { |
|---|
| 159 |
typedef typename Prefix<IdType>::Type PrefixType; |
|---|
| 160 |
|
|---|
| 161 |
typedef bool result_type; |
|---|
| 162 |
|
|---|
| 163 |
bool operator()(const PrefixType &prefix) const { |
|---|
| 164 |
IdType mask(KUtils::buildMask( |
|---|
| 165 |
prefix.second, KUtils::TypeToType<IdType>() |
|---|
| 166 |
)); |
|---|
| 167 |
|
|---|
| 168 |
return (m_id & mask) == (prefix.first & mask); |
|---|
| 169 |
} |
|---|
| 170 |
|
|---|
| 171 |
PrefixContainsId(const IdType &id) |
|---|
| 172 |
: m_id(id) |
|---|
| 173 |
{ } |
|---|
| 174 |
|
|---|
| 175 |
private: |
|---|
| 176 |
IdType m_id; |
|---|
| 177 |
}; |
|---|
| 178 |
|
|---|
| 179 |
/** |
|---|
| 180 |
* Kademlia standard contact |
|---|
| 181 |
* |
|---|
| 182 |
* @param N The number of bit used per key/id. Defaults to 160, |
|---|
| 183 |
* as described in kademlia draft. |
|---|
| 184 |
*/ |
|---|
| 185 |
template<unsigned N = 160> |
|---|
| 186 |
struct Contact { |
|---|
| 187 |
//! Number of bits per id |
|---|
| 188 |
enum { BITS = N }; |
|---|
| 189 |
|
|---|
| 190 |
//! Declare IdType |
|---|
| 191 |
typedef std::bitset<N> IdType; |
|---|
| 192 |
|
|---|
| 193 |
//! Declare PrefixType |
|---|
| 194 |
typedef std::pair<IdType, unsigned> PrefixType; |
|---|
| 195 |
|
|---|
| 196 |
//! Contact id |
|---|
| 197 |
IdType m_id; |
|---|
| 198 |
|
|---|
| 199 |
//! Contact address |
|---|
| 200 |
IPV4Address m_addr; |
|---|
| 201 |
|
|---|
| 202 |
//! Is implicitly casted to id if needed |
|---|
| 203 |
operator const IdType&() const { |
|---|
| 204 |
return m_id; |
|---|
| 205 |
} |
|---|
| 206 |
|
|---|
| 207 |
//! Equality test |
|---|
| 208 |
bool operator==(const Contact& t) const { |
|---|
| 209 |
return m_id == t.m_id && m_addr == t.m_addr; |
|---|
| 210 |
} |
|---|
| 211 |
|
|---|
| 212 |
//! Operator< overload for ordering |
|---|
| 213 |
bool operator<(const Contact& contact) const { |
|---|
| 214 |
return m_id < contact.m_id; |
|---|
| 215 |
} |
|---|
| 216 |
|
|---|
| 217 |
//! Constructor |
|---|
| 218 |
Contact() |
|---|
| 219 |
: m_id(0), m_addr() |
|---|
| 220 |
{ } |
|---|
| 221 |
}; |
|---|
| 222 |
|
|---|
| 223 |
/** |
|---|
| 224 |
* K-Bucket standard implementation |
|---|
| 225 |
* |
|---|
| 226 |
* @param ContactType Contact type to be used |
|---|
| 227 |
* @param K Maximum number of entry for this bucket, |
|---|
| 228 |
* defaults to 20 |
|---|
| 229 |
*/ |
|---|
| 230 |
template<typename ContactType_, unsigned K = 20> |
|---|
| 231 |
class KBucket { |
|---|
| 232 |
public: |
|---|
| 233 |
//! Throw'd when KBucket is full |
|---|
| 234 |
struct Full : public std::runtime_error { |
|---|
| 235 |
Full() : std::runtime_error("KBucket is full") { }; |
|---|
| 236 |
}; |
|---|
| 237 |
|
|---|
| 238 |
//! Contact type |
|---|
| 239 |
typedef ContactType_ ContactType; |
|---|
| 240 |
typedef typename ContactType::IdType IdType; |
|---|
| 241 |
|
|---|
| 242 |
//! Iterator type |
|---|
| 243 |
typedef typename std::list<ContactType>::iterator iterator; |
|---|
| 244 |
|
|---|
| 245 |
struct PrefixContainsId { |
|---|
| 246 |
typedef bool result_type; |
|---|
| 247 |
|
|---|
| 248 |
bool operator()(const KBucket &kbucket) const { |
|---|
| 249 |
const PrefixType &prefix(kbucket.m_prefix); |
|---|
| 250 |
|
|---|
| 251 |
IdType mask(KUtils::buildMask( |
|---|
| 252 |
prefix.second, KUtils::TypeToType<IdType>() |
|---|
| 253 |
)); |
|---|
| 254 |
|
|---|
| 255 |
return (m_id & mask) == (prefix.first & mask); |
|---|
| 256 |
} |
|---|
| 257 |
|
|---|
| 258 |
PrefixContainsId(const IdType &id) |
|---|
| 259 |
: m_id(id) |
|---|
| 260 |
{ } |
|---|
| 261 |
|
|---|
| 262 |
private: |
|---|
| 263 |
IdType m_id; |
|---|
| 264 |
}; |
|---|
| 265 |
|
|---|
| 266 |
//! Begin iterator |
|---|
| 267 |
iterator begin() { |
|---|
| 268 |
return entries.begin(); |
|---|
| 269 |
} |
|---|
| 270 |
|
|---|
| 271 |
//! End iterator |
|---|
| 272 |
iterator end() { |
|---|
| 273 |
return entries.end(); |
|---|
| 274 |
} |
|---|
| 275 |
|
|---|
| 276 |
//! Back inserter iterator |
|---|
| 277 |
std::back_insert_iterator< |
|---|
| 278 |
std::list<ContactType> |
|---|
| 279 |
> iitor() { |
|---|
| 280 |
return std::back_inserter(entries); |
|---|
| 281 |
} |
|---|
| 282 |
|
|---|
| 283 |
/** |
|---|
| 284 |
* Returns kbucket size |
|---|
| 285 |
*/ |
|---|
| 286 |
unsigned size() const { |
|---|
| 287 |
return entries.size(); |
|---|
| 288 |
} |
|---|
| 289 |
|
|---|
| 290 |
/** |
|---|
| 291 |
* Returns true if kbucket is full |
|---|
| 292 |
*/ |
|---|
| 293 |
bool isFull() const { |
|---|
| 294 |
return entries.size() == K; |
|---|
| 295 |
} |
|---|
| 296 |
|
|---|
| 297 |
/** |
|---|
| 298 |
* Add a contact |
|---|
| 299 |
* |
|---|
| 300 |
* @param contact Contact to be added |
|---|
| 301 |
* @param setAlive If contact is already present in kbucket, |
|---|
| 302 |
* move it to tail (means that contact is |
|---|
| 303 |
* alive) |
|---|
| 304 |
*/ |
|---|
| 305 |
void add(const ContactType& contact, bool setAlive = false) { |
|---|
| 306 |
iterator i = std::find(entries.begin(), entries.end(), contact); |
|---|
| 307 |
|
|---|
| 308 |
if(i == end()) { |
|---|
| 309 |
if(isFull()) { |
|---|
| 310 |
throw Full(); |
|---|
| 311 |
} |
|---|
| 312 |
|
|---|
| 313 |
logDebug(boost::format("KBucket is adding %s") |
|---|
| 314 |
% contact.m_id |
|---|
| 315 |
); |
|---|
| 316 |
|
|---|
| 317 |
entries.push_back(contact); |
|---|
| 318 |
} else if(setAlive) { |
|---|
| 319 |
// contact is already known, but since setAlive |
|---|
| 320 |
// flag is true, set it on the tail |
|---|
| 321 |
|
|---|
| 322 |
std::iter_swap(--end(), i); |
|---|
| 323 |
} |
|---|
| 324 |
} |
|---|
| 325 |
|
|---|
| 326 |
/** |
|---|
| 327 |
* Remove a contact |
|---|
| 328 |
*/ |
|---|
| 329 |
void remove(const ContactType &contact) { |
|---|
| 330 |
iterator i = entries.find(contact); |
|---|
| 331 |
|
|---|
| 332 |
if(i != end()) { |
|---|
| 333 |
entries.erase(i); |
|---|
| 334 |
} |
|---|
| 335 |
} |
|---|
| 336 |
|
|---|
| 337 |
/** |
|---|
| 338 |
* Constructor |
|---|
| 339 |
*/ |
|---|
| 340 |
KBucket() |
|---|
| 341 |
{ } |
|---|
| 342 |
|
|---|
| 343 |
/** |
|---|
| 344 |
* Copy constructor |
|---|
| 345 |
*/ |
|---|
| 346 |
KBucket(const KBucket& copy) |
|---|
| 347 |
: entries(copy.entries) |
|---|
| 348 |
{ } |
|---|
| 349 |
|
|---|
| 350 |
private: |
|---|
| 351 |
enum { |
|---|
| 352 |
NORMAL, |
|---|
| 353 |
WAITING_PING_REPLY |
|---|
| 354 |
} m_status; |
|---|
| 355 |
|
|---|
| 356 |
typedef typename Prefix<typename ContactType::IdType>::Type PrefixType; |
|---|
| 357 |
|
|---|
| 358 |
//! Bucket entries |
|---|
| 359 |
std::list<ContactType> entries; // FIXME, should be m_entries |
|---|
| 360 |
|
|---|
| 361 |
//! This bucket prefix |
|---|
| 362 |
PrefixType m_prefix; |
|---|
| 363 |
|
|---|
| 364 |
#ifdef FOR_FUTURE_USE |
|---|
| 365 |
ContactType m_pending; |
|---|
| 366 |
|
|---|
| 367 |
//! Process and entry |
|---|
| 368 |
void process(const ContactType &entry) { |
|---|
| 369 |
//! A predicate to lookup entries with id |
|---|
| 370 |
struct HasId { |
|---|
| 371 |
private: |
|---|
| 372 |
const Impl::Id &m_id; |
|---|
| 373 |
|
|---|
| 374 |
public: |
|---|
| 375 |
bool operator()(const Impl::Entry &entry) const { |
|---|
| 376 |
return entry.getId() == m_id; |
|---|
| 377 |
} |
|---|
| 378 |
|
|---|
| 379 |
//! Constructor |
|---|
| 380 |
HasId(id) : m_id(id) { } |
|---|
| 381 |
}; |
|---|
| 382 |
|
|---|
| 383 |
// FIXMEEEEEEEEEEE FIXME |
|---|
| 384 |
typename std::list<typename Impl::Entry>::iterator itor; |
|---|
| 385 |
|
|---|
| 386 |
if(itor = std::find( |
|---|
| 387 |
entries.begin(), |
|---|
| 388 |
entries.end(), |
|---|
| 389 |
entry |
|---|
| 390 |
//HasId(entry.getId()) |
|---|
| 391 |
)) { |
|---|
| 392 |
// Known id, move to tail |
|---|
| 393 |
std::iter_swap(itor, --entries.end()); |
|---|
| 394 |
} else if(entries.size() < K) { |
|---|
| 395 |
// Not found with free space |
|---|
| 396 |
entries.push_back(entry); |
|---|
| 397 |
} else if(m_status == NORMAL) { |
|---|
| 398 |
// Not found without free space and no pending entry |
|---|
| 399 |
m_pending = entry; |
|---|
| 400 |
m_status = WAITING_PING_REPLY; |
|---|
| 401 |
|
|---|
| 402 |
pingFirst(); |
|---|
| 403 |
} else if(m_status = WAITING_PING_REPLY) { |
|---|
| 404 |
// Insert previous pending entry |
|---|
| 405 |
pingReply(m_pending, false); |
|---|
| 406 |
} |
|---|
| 407 |
} |
|---|
| 408 |
|
|---|
| 409 |
void pingReply(typename Impl::Entry &entry, bool result) { |
|---|
| 410 |
if(entry == m_pending) { |
|---|
| 411 |
if(!result) { |
|---|
| 412 |
// Remove first element |
|---|
| 413 |
entries.pop_front(); |
|---|
| 414 |
|
|---|
| 415 |
// Add the pending element |
|---|
| 416 |
entries.push_back(m_pending); |
|---|
| 417 |
|
|---|
| 418 |
// Set status back to normal |
|---|
| 419 |
m_status = NORMAL; |
|---|
| 420 |
} else { |
|---|
| 421 |
// First element answered, move it to tail and |
|---|
| 422 |
ping 2nd |
|---|
| 423 |
std::iter_swap( |
|---|
| 424 |
entries.begin(), --entries.end() |
|---|
| 425 |
); |
|---|
| 426 |
|
|---|
| 427 |
pingFirst(); |
|---|
| 428 |
} |
|---|
| 429 |
} |
|---|
| 430 |
} |
|---|
| 431 |
|
|---|
| 432 |
void pingFirst() { |
|---|
| 433 |
Impl::ping( |
|---|
| 434 |
boost::bind(&pingReply, this, entries.front(), _1) |
|---|
| 435 |
); |
|---|
| 436 |
} |
|---|
| 437 |
#endif |
|---|
| 438 |
}; |
|---|
| 439 |
|
|---|
| 440 |
/** |
|---|
| 441 |
* Given a std::pair, extract the first entry |
|---|
| 442 |
*/ |
|---|
| 443 |
template<typename R> |
|---|
| 444 |
struct ExtractFirst { |
|---|
| 445 |
typedef R result_type; |
|---|
| 446 |
|
|---|
| 447 |
template<typename T, typename U> |
|---|
| 448 |
result_type operator()(const std::pair<T, U>& t) const { |
|---|
| 449 |
return t.first; |
|---|
| 450 |
} |
|---|
| 451 |
}; |
|---|
| 452 |
|
|---|
| 453 |
/** |
|---|
| 454 |
* Functor that derefences an iterator |
|---|
| 455 |
*/ |
|---|
| 456 |
template< |
|---|
| 457 |
typename T |
|---|
| 458 |
> |
|---|
| 459 |
struct DereferenceIterator { |
|---|
| 460 |
typedef T result_type; |
|---|
| 461 |
|
|---|
| 462 |
template<class I> |
|---|
| 463 |
T operator()(const I &itor) { |
|---|
| 464 |
return *itor; |
|---|
| 465 |
} |
|---|
| 466 |
}; |
|---|
| 467 |
|
|---|
| 468 |
/** |
|---|
| 469 |
* Returns the first id of a given prefix |
|---|
| 470 |
*/ |
|---|
| 471 |
template< |
|---|
| 472 |
typename IdType |
|---|
| 473 |
> |
|---|
| 474 |
IdType prefixBase(const typename Prefix<IdType>::Type &prefix) { |
|---|
| 475 |
return prefix.first & KUtils::buildMask( |
|---|
| 476 |
prefix.second, |
|---|
| 477 |
KUtils::TypeToType<IdType>() |
|---|
| 478 |
); |
|---|
| 479 |
} |
|---|
| 480 |
|
|---|
| 481 |
/** |
|---|
| 482 |
* Functor that compares two predicate using their distance from a given id. |
|---|
| 483 |
* |
|---|
| 484 |
* @param IdType Type of id object |
|---|
| 485 |
*/ |
|---|
| 486 |
template< |
|---|
| 487 |
typename IdType |
|---|
| 488 |
> |
|---|
| 489 |
struct PrefixDistanceFromLess { |
|---|
| 490 |
typedef typename Prefix<IdType>::Type PrefixType; |
|---|
| 491 |
|
|---|
| 492 |
typedef bool result_type; |
|---|
| 493 |
|
|---|
| 494 |
bool operator()(const PrefixType &t, const PrefixType &u) const { |
|---|
| 495 |
return |
|---|
| 496 |
(prefixBase<IdType>(t) | m_id) |
|---|
| 497 |
< |
|---|
| 498 |
(prefixBase<IdType>(u) | m_id); |
|---|
| 499 |
} |
|---|
| 500 |
|
|---|
| 501 |
PrefixDistanceFromLess(const IdType &id) |
|---|
| 502 |
: m_id(id) |
|---|
| 503 |
{ } |
|---|
| 504 |
|
|---|
| 505 |
private: |
|---|
| 506 |
IdType m_id; |
|---|
| 507 |
}; |
|---|
| 508 |
|
|---|
| 509 |
/** |
|---|
| 510 |
* RoutingTable |
|---|
| 511 |
* |
|---|
| 512 |
* @param KBucketType_ Used KBucket type |
|---|
| 513 |
* @param RPCFunctor Callback for RPCs (currently not implemented) |
|---|
| 514 |
*/ |
|---|
| 515 |
template< |
|---|
| 516 |
typename KBucketType_, |
|---|
| 517 |
typename RPCFunctor |
|---|
| 518 |
> |
|---|
| 519 |
class RoutingTable { |
|---|
| 520 |
public: |
|---|
| 521 |
//! Public types |
|---|
| 522 |
|
|---|
| 523 |
//@{ |
|---|
| 524 |
typedef KBucketType_ KBucketType; |
|---|
| 525 |
typedef typename KBucketType::ContactType ContactType; |
|---|
| 526 |
typedef typename ContactType::IdType IdType; |
|---|
| 527 |
typedef typename Prefix<IdType>::Type PrefixType; |
|---|
| 528 |
//@} |
|---|
| 529 |
|
|---|
| 530 |
private: |
|---|
| 531 |
//! Private types |
|---|
| 532 |
|
|---|
| 533 |
//@{ |
|---|
| 534 |
typedef std::map<PrefixType, KBucketType, PrefixLess<IdType> > RMap; |
|---|
| 535 |
//@} |
|---|
| 536 |
|
|---|
| 537 |
public: |
|---|
| 538 |
//! Number of bits per id |
|---|
| 539 |
enum { BITS = ContactType::BITS }; |
|---|
| 540 |
|
|---|
| 541 |
//! Dump (DEBUG) |
|---|
| 542 |
void dump() { |
|---|
| 543 |
typename RMap::iterator itor = m_tree.begin(); |
|---|
| 544 |
typename KBucketType::iterator jtor; |
|---|
| 545 |
|
|---|
| 546 |
for(; itor != m_tree.end(); itor++) { |
|---|
| 547 |
logDebug( |
|---|
| 548 |
boost::format("%s/%i") |
|---|
| 549 |
% KUtils::bitsetBitDump(itor->first.first) |
|---|
| 550 |
% itor->first.second |
|---|
| 551 |
); |
|---|
| 552 |
|
|---|
| 553 |
for( |
|---|
| 554 |
jtor = itor->second.begin(); |
|---|
| 555 |
jtor != itor->second.end(); |
|---|
| 556 |
++jtor |
|---|
| 557 |
) { |
|---|
| 558 |
logDebug(boost::format(" %s") |
|---|
| 559 |
% KUtils::bitsetBitDump(jtor->m_id) |
|---|
| 560 |
); |
|---|
| 561 |
} |
|---|
| 562 |
} |
|---|
| 563 |
} |
|---|
| 564 |
|
|---|
| 565 |
ContactType &getRandom() { |
|---|
| 566 |
static typename RMap::iterator itor = m_tree.begin(); |
|---|
| 567 |
|
|---|
| 568 |
while(itor->second.size() == 0) { |
|---|
| 569 |
++itor; |
|---|
| 570 |
} |
|---|
| 571 |
|
|---|
| 572 |
return *(itor->second.begin()); |
|---|
| 573 |
} |
|---|
| 574 |
|
|---|
| 575 |
/** |
|---|
| 576 |
* Add a contact |
|---|
| 577 |
* |
|---|
| 578 |
* @param contact The contact to be added. |
|---|
| 579 |
* @param setAlive Sets the contact to alive (a packet has been received |
|---|
| 580 |
* from there). Defaults to false. |
|---|
| 581 |
*/ |
|---|
| 582 |
void add(const ContactType& contact, bool setAlive = false) { |
|---|
| 583 |
typename RMap::iterator itor; |
|---|
| 584 |
|
|---|
| 585 |
itor = std::find_if(m_tree.begin(), m_tree.end(), |
|---|
| 586 |
boost::bind( |
|---|
| 587 |
PrefixContainsId<IdType>( |
|---|
| 588 |
contact.m_id ^ m_self.m_id |
|---|
| 589 |
), boost::bind( |
|---|
| 590 |
ExtractFirst<typename RMap::key_type>(), |
|---|
| 591 |
_1 |
|---|
| 592 |
) |
|---|
| 593 |
) |
|---|
| 594 |
); |
|---|
| 595 |
|
|---|
| 596 |
CHECK_THROW(itor != m_tree.end()); |
|---|
| 597 |
|
|---|
| 598 |
try { |
|---|
| 599 |
// Add contact to KBucket |
|---|
| 600 |
itor->second.add(contact, setAlive); |
|---|
| 601 |
} catch(typename KBucketType::Full &e) { |
|---|
| 602 |
// KBucket is full: split and retry |
|---|
| 603 |
split(itor); |
|---|
| 604 |
|
|---|
| 605 |
add(contact, setAlive); |
|---|
| 606 |
} |
|---|
| 607 |
} |
|---|
| 608 |
|
|---|
| 609 |
/** |
|---|
| 610 |
* Remove a contact |
|---|
| 611 |
*/ |
|---|
| 612 |
void remove(const ContactType &); |
|---|
| 613 |
|
|---|
| 614 |
/** |
|---|
| 615 |
* Returns the prefix who contains a given id |
|---|
| 616 |
* |
|---|
| 617 |
* @param id Id to be contained by returned prefix |
|---|
| 618 |
*/ |
|---|
| 619 |
typename RMap::iterator getOwningPrefix(const IdType &id) { |
|---|
| 620 |
return std::find_if(m_tree.begin(), m_tree.end(), |
|---|
| 621 |
boost::bind( |
|---|
| 622 |
PrefixContainsId<IdType>(id), |
|---|
| 623 |
boost::bind( |
|---|
| 624 |
ExtractFirst<typename RMap::key_type>(), |
|---|
| 625 |
_1 |
|---|
| 626 |
) |
|---|
| 627 |
) |
|---|
| 628 |
); |
|---|
| 629 |
} |
|---|
| 630 |
|
|---|
| 631 |
/** |
|---|
| 632 |
* Find closest ids to a given id. |
|---|
| 633 |
* |
|---|
| 634 |
* @param id Id to be used while searching. |
|---|
| 635 |
*/ |
|---|
| 636 |
std::list<ContactType> findClosestToId(const IdType &id) { |
|---|
| 637 |
typename RMap::iterator itor = getOwningPrefix(id); |
|---|
| 638 |
std::list<ContactType> list; |
|---|
| 639 |
|
|---|
| 640 |
CHECK_THROW(itor != m_tree.end()); |
|---|
| 641 |
|
|---|
| 642 |
// Copy contacts from nearest kbucket |
|---|
| 643 |
std::copy( |
|---|
| 644 |
itor->second.begin(), |
|---|
| 645 |
itor->second.end(), |
|---|
| 646 |
std::back_inserter(list) |
|---|
| 647 |
); |
|---|
| 648 |
|
|---|
| 649 |
// Not enough contacts: find closest prefixes |
|---|
| 650 |
if(list.size() < 10) { |
|---|
| 651 |
typename RMap::iterator jtor(itor); |
|---|
| 652 |
std::vector<typename RMap::iterator> v; |
|---|
| 653 |
|
|---|
| 654 |
for( |
|---|
| 655 |
typename RMap::iterator zitor = m_tree.begin(); |
|---|
| 656 |
zitor != m_tree.end(); |
|---|
| 657 |
++zitor |
|---|
| 658 |
) { |
|---|
| 659 |
v.push_back(zitor); |
|---|
| 660 |
} |
|---|
| 661 |
|
|---|
| 662 |
|
|---|
| 663 |
if(jtor != m_tree.begin()) { |
|---|
| 664 |
do { |
|---|
| 665 |
v.push_back(--jtor); |
|---|
| 666 |
} while(jtor != m_tree.begin()); |
|---|
| 667 |
} |
|---|
| 668 |
|
|---|
| 669 |
jtor++ = itor; |
|---|
| 670 |
|
|---|
| 671 |
while(jtor != m_tree.end()) { |
|---|
| 672 |
v.push_back(jtor++); |
|---|
| 673 |
} |
|---|
| 674 |
|
|---|
| 675 |
// PrefixDistanceFromLess( |
|---|
| 676 |
// ExtractFirst(DereferenceIterator(_1)), |
|---|
| 677 |
// ExtractFirst(DereferenceIterator(_2)) |
|---|
| 678 |
// ) |
|---|
| 679 |
|
|---|
| 680 |
typedef typename RMap::key_type RMKey; |
|---|
| 681 |
typedef typename RMap::value_type RMValue; |
|---|
| 682 |
|
|---|
| 683 |
// Now order prefixes by distance |
|---|
| 684 |
std::sort(v.begin(), v.end(), |
|---|
| 685 |
boost::bind( |
|---|
| 686 |
PrefixDistanceFromLess<IdType>(id), |
|---|
| 687 |
boost::bind( |
|---|
| 688 |
ExtractFirst<RMKey>(), |
|---|
| 689 |
boost::bind( |
|---|
| 690 |
DereferenceIterator< |
|---|
| 691 |
RMValue |
|---|
| 692 |
>(), _1 |
|---|
| 693 |
) |
|---|
| 694 |
), |
|---|
| 695 |
boost::bind( |
|---|
| 696 |
ExtractFirst<RMKey>(), |
|---|
| 697 |
boost::bind( |
|---|
| 698 |
DereferenceIterator< |
|---|
| 699 |
RMValue |
|---|
| 700 |
>(), _2 |
|---|
| 701 |
) |
|---|
| 702 |
) |
|---|
| 703 |
) |
|---|
| 704 |
); |
|---|
| 705 |
|
|---|
| 706 |
typename std::vector< |
|---|
| 707 |
typename RMap::iterator |
|---|
| 708 |
>::iterator kitor = v.begin(); |
|---|
| 709 |
|
|---|
| 710 |
while(list.size() < 10 && kitor != v.end()) { |
|---|
| 711 |
// Copy contacts from nearest kbucket |
|---|
| 712 |
std::copy( |
|---|
| 713 |
(*kitor)->second.begin(), |
|---|
| 714 |
(*kitor)->second.end(), |
|---|
| 715 |
std::back_inserter(list) |
|---|
| 716 |
); |
|---|
| 717 |
|
|---|
| 718 |
kitor++; |
|---|
| 719 |
} |
|---|
| 720 |
} |
|---|
| 721 |
|
|---|
| 722 |
return list; |
|---|
| 723 |
} |
|---|
| 724 |
|
|---|
| 725 |
/** |
|---|
| 726 |
* Constructor |
|---|
| 727 |
* |
|---|
| 728 |
* @param f RPC callback functor |
|---|
| 729 |
*/ |
|---|
| 730 |
RoutingTable(RPCFunctor f) |
|---|
| 731 |
: m_rpcHandler(f) |
|---|
| 732 |
{ |
|---|
| 733 |
IdType id; |
|---|
| 734 |
id.reset(); |
|---|
| 735 |
|
|---|
| 736 |
m_tree.insert(std::make_pair( |
|---|
| 737 |
std::make_pair(id, 0), |
|---|
| 738 |
KBucketType() |
|---|
| 739 |
)); |
|---|
| 740 |
} |
|---|
| 741 |
|
|---|
| 742 |
//! Iterator forward declaration |
|---|
| 743 |
struct Iterator; |
|---|
| 744 |
typedef Iterator iterator; |
|---|
| 745 |
|
|---|
| 746 |
//! Our id |
|---|
| 747 |
ContactType m_self; |
|---|
| 748 |
|
|---|
| 749 |
private: |
|---|
| 750 |
//! Routing table |
|---|
| 751 |
RMap m_tree; |
|---|
| 752 |
|
|---|
| 753 |
//! RPC Functor |
|---|
| 754 |
RPCFunctor m_rpcHandler; |
|---|
| 755 |
|
|---|
| 756 |
static IdType xorFun(const IdType& t, const IdType& u) { |
|---|
| 757 |
return t ^ u; |
|---|
| 758 |
} |
|---|
| 759 |
|
|---|
| 760 |
void split(typename RMap::iterator itor) { |
|---|
| 761 |
PrefixType lprefix(itor->first), rprefix(itor->first); |
|---|
| 762 |
|
|---|
| 763 |
lprefix.first[itor->first.second] = 0; |
|---|
| 764 |
rprefix.first[itor->first.second] = 1; |
|---|
| 765 |
|
|---|
| 766 |
lprefix.second++; |
|---|
| 767 |
rprefix.second++; |
|---|
| 768 |
|
|---|
| 769 |
KBucketType lbucket, rbucket; |
|---|
| 770 |
|
|---|
| 771 |
std::remove_copy_if( |
|---|
| 772 |
itor->second.begin(), |
|---|
| 773 |
itor->second.end(), |
|---|
| 774 |
rbucket.iitor(), |
|---|
| 775 |
boost::bind(IdBelongsToPrefix<IdType>(lprefix), |
|---|
| 776 |
boost::bind(&xorFun, m_self.m_id, _1) |
|---|
| 777 |
) |
|---|
| 778 |
); |
|---|
| 779 |
|
|---|
| 780 |
std::set_difference( |
|---|
| 781 |
itor->second.begin(), |
|---|
| 782 |
itor->second.end(), |
|---|
| 783 |
rbucket.begin(), |
|---|
| 784 |
rbucket.end(), |
|---|
| 785 |
lbucket.iitor() |
|---|
| 786 |
); |
|---|
| 787 |
|
|---|
| 788 |
CHECK_THROW( |
|---|
| 789 |
rbucket.size() + lbucket.size() == itor->second.size() |
|---|
| 790 |
); |
|---|
| 791 |
|
|---|
| 792 |
m_tree.erase(itor); |
|---|
| 793 |
|
|---|
| 794 |
m_tree.insert(std::make_pair(lprefix, lbucket)); |
|---|
| 795 |
m_tree.insert(std::make_pair(rprefix, rbucket)); |
|---|
| 796 |
} |
|---|
| 797 |
|
|---|
| 798 |
public: |
|---|
| 799 |
//! Iterator |
|---|
| 800 |
class Iterator |
|---|
| 801 |
: public std::iterator< |
|---|
| 802 |
std::forward_iterator_tag, |
|---|
| 803 |
ContactType, |
|---|
| 804 |
ptrdiff_t, |
|---|
| 805 |
ContactType *, |
|---|
| 806 |
ContactType & |
|---|
| 807 |
> { |
|---|
| 808 |
typename RMap::iterator m_mIter; |
|---|
| 809 |
typename KBucketType::iterator m_kIter; |
|---|
| 810 |
|
|---|
| 811 |
//! Iterator increment |
|---|
| 812 |
void increment() { |
|---|
| 813 |
typename RMap::iterator mNext(m_mIter); |
|---|
| 814 |
|
|---|
| 815 |
if(m_kIter == m_mIter->second.end()) { |
|---|
| 816 |
m_kIter = (++m_mIter)->second.begin(); |
|---|
| 817 |
} |
|---|
| 818 |
|
|---|
| 819 |
m_kIter++; |
|---|
| 820 |
} |
|---|
| 821 |
|
|---|
| 822 |
//! Constructor |
|---|
| 823 |
Iterator( |
|---|
| 824 |
typename RMap::iterator mIter, |
|---|
| 825 |
typename KBucketType::iterator kIter |
|---|
| 826 |
) |
|---|
| 827 |
: m_mIter(mIter), m_kIter(kIter) |
|---|
| 828 |
{ } |
|---|
| 829 |
|
|---|
| 830 |
friend class RoutingTable; |
|---|
| 831 |
public: |
|---|
| 832 |
//! Preincrement |
|---|
| 833 |
Iterator &operator++() { |
|---|
| 834 |
increment(); |
|---|
| 835 |
|
|---|
| 836 |
return *this; |
|---|
| 837 |
} |
|---|
| 838 |
|
|---|
| 839 |
//! Postincrement |
|---|
| 840 |
Iterator operator++(int) { |
|---|
| 841 |
Iterator i(*this); |
|---|
| 842 |
|
|---|
| 843 |
increment(); |
|---|
| 844 |
|
|---|
| 845 |
return i; |
|---|
| 846 |
} |
|---|
| 847 |
|
|---|
| 848 |
//! Dereference |
|---|
| 849 |
ContactType &operator*() { |
|---|
| 850 |
if(m_kIter == m_mIter->second.end()) { |
|---|
| 851 |
typename RMap::iterator mNext(m_mIter); |
|---|
| 852 |
|
|---|
| 853 |
return *(++mNext)->second.begin(); |
|---|
| 854 |
} |
|---|
| 855 |
|
|---|
| 856 |
return *m_kIter; |
|---|
| 857 |
} |
|---|
| 858 |
|
|---|
| 859 |
//! Member access |
|---|
| 860 |
ContactType *operator->() { |
|---|
| 861 |
if(m_kIter == m_mIter->second.end()) { |
|---|
| 862 |
typename RMap::iterator mNext(m_mIter); |
|---|
| 863 |
|
|---|
| 864 |
return &*(++mNext)->second.begin(); |
|---|
| 865 |
} |
|---|
| 866 |
|
|---|
| 867 |
return &(*m_kIter); |
|---|
| 868 |
} |
|---|
| 869 |
|
|---|
| 870 |
//! Equality test |
|---|
| 871 |
bool operator==(const Iterator &t) const { |
|---|
| 872 |
return m_mIter == t.m_mIter && m_kIter == t.m_kIter; |
|---|
| 873 |
} |
|---|
| 874 |
|
|---|
| 875 |
//! Inequality test |
|---|
| 876 |
bool operator!=(const Iterator &t) const { |
|---|
| 877 |
return !(*this == t); |
|---|
| 878 |
} |
|---|
| 879 |
}; |
|---|
| 880 |
|
|---|
| 881 |
Iterator begin() { |
|---|
| 882 |
return Iterator(m_tree.begin(), m_tree.begin()->second.begin()); |
|---|
| 883 |
} |
|---|
| 884 |
|
|---|
| 885 |
Iterator end() { |
|---|
| 886 |
return Iterator(--m_tree.end(), (--m_tree.end())->second.end()); |
|---|
| 887 |
} |
|---|
| 888 |
}; |
|---|
| 889 |
|
|---|
| 890 |
} |
|---|
| 891 |
|
|---|
| 892 |
namespace std { |
|---|
| 893 |
|
|---|
| 894 |
/** |
|---|
| 895 |
* Compare two bitsets threading them as numbers (bit[0] is evaluated as LSB) |
|---|
| 896 |
*/ |
|---|
| 897 |
template<size_t N> |
|---|
| 898 |
bool operator<(const std::bitset<N>& a, const std::bitset<N>& b) { |
|---|
| 899 |
for(int i = N - 1; i >= 0; --i) { |
|---|
| 900 |
if(a[i] < b[i]) |
|---|
| 901 |
return true; |
|---|
| 902 |
} |
|---|
| 903 |
|
|---|
| 904 |
return false; |
|---|
| 905 |
} |
|---|
| 906 |
|
|---|
| 907 |
} |
|---|
| 908 |
|
|---|
| 909 |
#endif |
|---|