/* This Work is under GPL provided with this work. This work is based on the java implementation of the Kademlia protocol. Kademlia: Peer-to-peer routing based on the XOR metric Copyright (C) 2002 Petar Maymounkov [petar@post.harvard.edu] http://kademlia.scs.cs.nyu.edu and This work is bassed on translation from Barry Dunne to C++ Copyright (C)2003 Barry Dunne (http://www.emule-project.net) */ #include "cBucket.h" #include "cPeer.h" #include "misc.h" #include "opcodes.h" cBucket::~cBucket() {{{ cPeerList::const_iterator it; if (!dontDeleteContacts) for (it = contacts.begin(); it != contacts.end(); it++) delete *it; contacts.clear(); }}} bool cBucket::add(class cPeer *CONTACT) {{{ if (CONTACT == NULL) return false; class cPeer *c = getContact(CONTACT->get_Hash()->hash); if (c != NULL) { // Move to the end of the list remove(c); contacts.push_back(c); return false; } if (contacts.size() < OVERNET_BUCKET) { // If not full, add to end of list contacts.push_back(CONTACT); return true; } return false; }}} void cBucket::setAlive(uint32_t IP, uint16_t PORT) {{{ if (contacts.empty()) return; cPeer *c = NULL; cPeerList::iterator it; cPeerList::iterator end = contacts.end(); for (it = contacts.begin(); it != end; it++) { c = *it; if (! ((IP == c->ip) && (PORT == c->udp))) continue; c->madeContact = true; c->expires = 0; // Move to the end of the list remove(c); contacts.push_back(c); return; } }}} class cPeer *cBucket::getContact(const uint8_t *KEY) {{{ cPeerList::const_iterator it; for (it = contacts.begin(); it != contacts.end(); it++) { if (0 == memcmp(KEY, ((*it)->get_Hash()), 16)) { return *it; break; } } return NULL; }}} void cBucket::getContacts (cPeerList *result, bool emptyFirst) {{{ if (emptyFirst) result->clear(); if (contacts.size() > 0) result->insert(result->end(), contacts.begin(), contacts.end()); }}} class cPeer *cBucket::getOldest (void) {{{ if (contacts.size() > 0) return contacts.front(); return NULL; }}} size_t cBucket::getClosest (const uint8_t *KEY, size_t maxRequired, cPeerMap *result, bool emptyFirst) {{{ if (contacts.size() == 0) return 0; if (emptyFirst) result->clear(); size_t count = 0; cPeerList::const_iterator it; for (it = contacts.begin(); it != contacts.end(); it++) { cHash dist; memcpy (dist.hash, (*it)->get_Hash()->hash, 16); xor_128(dist.hash, KEY); (*result)[dist] = *it; if (++count == maxRequired) return count; } return count; }}} void cBucket::dumpContents(void) {{{ cPeerList::const_iterator it; for (it = contacts.begin(); it != contacts.end(); it++) { cPeer *c = *it; struct in_addr ip; ip.s_addr = c->ip; printf("\t%s", hash_bin2hex(c->get_Hash()->hash)); printf("\t%s (%u)", inet_ntoa(ip), c->udp); printf("\t%20s", c->get_Name()); printf("\tDistance: %s\n", hash_bin2hex(c->get_Dist()->hash)); } }}}