ndn-js-contrib
Version:
Reusable 'Classes' for Named Data Networking: NameTree, PIT, FIB, ContentStore, Interfaces, and Transports
195 lines (156 loc) • 5.08 kB
JavaScript
var binarySearch = require("./../Utility/binarySearch.js")
, ndn
, debug = {};
debug.debug = require("debug")("PIT");
function pubKeyMatch (ar1, ar2){
if (!ar1){
return true;
}
for(var i = 0; i < ar1.length; i++ ){
if (ar1[i] !== ar2[i]){
return false;
}
}
return true;
}
/**PIT Entry
*@constructor
*@param {Buffer} element The raw interest data packet
*@param {Object=} interest the ndn.Interest Object
*@param {number|function} faceIDorCallback Either the faceID of the face this interest was received on, or a callback function to receive any matching data
*@returns {PitEntry} - the entry
*/
function PitEntry (element, interest, faceIDorCallback){
if (typeof interest !== "object"){
faceIDorCallback = interest;
interest = new ndn.Interest();
interest.wireDecode(element);
}
if (!interest.nonce){
interest.wireDecode(element);
}
this.nonce = interest.nonce;
this.uri = interest.name.toUri();
this.interest = interest;
this.element = element;
if (typeof faceIDorCallback === "function" ){
this.callback = faceIDorCallback;
} else {
this.faceID = faceIDorCallback;
}
return this;
}
/**Test whether the PitEntry is fulfilled by a data object
*@param {Object} data the ndn.Data object
*@returns {Boolean}
*/
PitEntry.prototype.matches = function(data){
if (this.interest.matchesName(data.name)
&& pubKeyMatch(this.interest.publisherPublicKeyDigest, data.signedInfo.publisher.publisherPublicKeyDigest)
){
return true;
} else {
return false;
}
};
/**Consume the PitEntry (assuming it is attached to a the nameTree)
*@returns {PitEntry} in case you want to do anything with it afterward
*/
PitEntry.prototype.consume = function(callbackCalled) {
if (this.nameTreeNode){
var i = binarySearch(this.nameTreeNode.pitEntries, this, "nonce");
if (i >= 0){
var removed = this.nameTreeNode.pitEntries.splice(~i, 1)[0];
if (removed.callback && !callbackCalled){
removed.callback(null, removed.interest);
}
}
}
return this;
};
/**Pending Interest Table
*@constructor
*@param {NameTree} nameTree the nameTree to build the table on top of
*@returns {PIT} a new PIT
*/
var PIT = function PIT(nameTree){
this.nameTree = nameTree;
return this;
};
/**Import ndn-lib into the PIT scope
*@param {Object} NDN the NDN-js library in object form
*/
PIT.installNDN = function(NDN){
ndn = NDN;
return this;
};
PIT.Entry = PitEntry;
PIT.prototype.useNameTree = function(nameTree){
this.nameTree = nameTree;
return this;
};
/**Create and insert a new {@link PITEntry}
*@param {Buffer} element The raw interest data packet
*@param {Object=} interest the ndn.Interest object
*@param {Number|function} faceIDorCallback either a numerical faceID or a callbackFunction
*@returns {PIT} the PIT (for chaining)
*/
PIT.prototype.insertPitEntry = function(element, interest, faceIDorCallback){
var pitEntry = new PIT.Entry(element, interest, faceIDorCallback);
//console.log(new Error("pitConstructStackCheck").stack)
setTimeout(function(){
pitEntry.consume();
}, pitEntry.interest.getInterestLifetimeMilliseconds() || 10);
var node = this.nameTree.lookup(pitEntry.interest.name);
var i = binarySearch(node.pitEntries, pitEntry, "nonce");
if (i < 0){
pitEntry.nameTreeNode = node;
node.pitEntries.splice(~i, 0 ,pitEntry);
}
return this;
};
PIT.prototype.checkDuplicate = function(interest){
var node = this.nameTree.lookup(interest.name);
var i = binarySearch(node.pitEntries, interest, "nonce");
if (i < 0){
return false;
} else {
return true;
}
};
/**Lookup the PIT for Entries matching a given data object
*@param {Object} data The ndn.Data object
*@returns {Object} results: an object with two properties, pitEntries and faces, which are
* an array of matching {@link PITEntry}s and
* an sorted array of faceIDs for use with {@link Interfaces.dispatch}, respectively.
*/
PIT.prototype.lookup = function(data, name, matches, faceIDs){
name = name || data.name;
matches = matches || [];
faceIDs = faceIDs || [];
var pitEntries = this.nameTree.lookup(name).pitEntries;
for (var i = 0; i < pitEntries.length; i++){
if (pitEntries[i].matches(data)){
matches.push(pitEntries[i]);
if (pitEntries[i].faceID !== (null || undefined)){
if ((faceIDs.length === 0) || (faceIDs[faceIDs.length - 1] > pitEntries[i].faceID)){
faceIDs.push(pitEntries[i].faceID);
} else {
for (var j = faceIDs.length - 1; j >= 0; j--){
if (faceIDs[j] > pitEntries[i].faceID){
faceIDs.splice(j+1,0, pitEntries[i].faceID);
} else if (faceIDs[j] === pitEntries[i].faceID){
break;
}
}
}
}
}
}
if (name.size() > 0){
return this.lookup(data, name.getPrefix(-1), matches, faceIDs);
} else{
return {pitEntries : matches, faces : faceIDs};
}
};
module.exports = PIT;