wikimedia-kad-fork
Version:
implementation of the kademlia dht for node
116 lines (95 loc) • 2.59 kB
JavaScript
;
var _ = require('lodash');
var assert = require('assert');
var constants = require('./constants');
var Contact = require('./contact');
/**
* A bucket is a "column" of the routing table. It is an array-like object that
* holds {@link Contact}s.
* @constructor
*/
function Bucket() {
if (!(this instanceof Bucket)) {
return new Bucket();
}
this._contacts = [];
}
/**
* Return the number of contacts in this bucket
* @returns {Number}
*/
Bucket.prototype.getSize = function() {
return this._contacts.length;
};
/**
* Return the list of contacts in this bucket
* @returns {Array}
*/
Bucket.prototype.getContactList = function() {
return _.clone(this._contacts);
};
/**
* Return the contact at the given index
* @param {Number} index - Index of contact in bucket
* @returns {Contact|null}
*/
Bucket.prototype.getContact = function(index) {
assert(index >= 0, 'Contact index cannot be negative');
assert(index < constants.K, 'Contact index cannot be greater than K');
return this._contacts[index] || null;
};
/**
* Adds the contact to the bucket
* @param {Contact} contact - Contact instance to add to bucket
* @returns {Bucket}
*/
Bucket.prototype.addContact = function(contact) {
assert(contact instanceof Contact, 'Invalid contact supplied');
if (!this.hasContact(contact.nodeID)) {
var index = _.sortedIndex(this._contacts, contact, function(contact) {
return contact.lastSeen;
});
this._contacts.splice(index, 0, contact);
}
return this;
};
/**
* Removes the contact from the bucket
* @param {Contact} contact - Contact instance to remove from bucket
* @returns {Bucket}
*/
Bucket.prototype.removeContact = function(contact) {
var index = this.indexOf(contact);
if (index >= 0) {
this._contacts.splice(index, 1);
}
return this;
};
/**
* Returns boolean indicating that the nodeID is contained in the bucket
* @param {String} nodeID - 160 bit node ID
* @returns {Boolean}
*/
Bucket.prototype.hasContact = function(nodeID) {
for (var i = 0; i < this.getSize(); i++) {
if (this._contacts[i].nodeID === nodeID) {
return true;
}
}
return false;
};
/**
* Returns the index of the given contact
* @param {Contact} contact - Contact instance for index check
* @returns {Number}
*/
Bucket.prototype.indexOf = function(contact) {
assert(contact instanceof Contact, 'Invalid contact supplied');
for (var i = 0; i < this.getSize(); i++) {
if (this.getContact(i).nodeID === contact.nodeID) {
return i;
}
}
return -1;
};
module.exports = Bucket;