root/hydranode/hncore/kademlia.h

Revision 2079, 17.9 kB (checked in by madcat, 3 years ago)

Removed executable property.

Line 
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
Note: See TracBrowser for help on using the browser.