ndn-js-contrib
Version:
Reusable 'Classes' for Named Data Networking: NameTree, PIT, FIB, ContentStore, Interfaces, and Transports
208 lines (157 loc) • 5.05 kB
JavaScript
var ndn
, Face
, debug = {}
, ndn = require("ndn-js")
, TlvDecoder = require("ndn-js/js/encoding/tlv/tlv-decoder.js").TlvDecoder
, Tlv = require("ndn-js/js/encoding/tlv/tlv.js").Tlv;
debug.debug= require("debug")("Interfaces");
/**Interface manager
*@constructor
*@param {Subject} Subject - a {@link Subject} instance
*@returns {Interfaces} - a new Interface manager
*/
var Interfaces = function Interfaces(Subject){
this.subject = Subject;
this.transports = {};
Face = ndn.Face;
this.Faces = new Interfaces.List();
return this;
};
/**Class method to install ndn-lib. Only necessary if you require("ndn-classes/src/DataStructures/Interfaces.js"), done for you if require('ndn-classes').Interfaces
*@private
*@param {Object} - NDN the ndn-lib object
*/
Interfaces.installNDN = function(NDN){
ndn = NDN;
return this;
};
Interfaces.prototype.transports = {};
Interfaces.List = function(){
this.head = null;
this.size = 0;
this.index = 0;
return this;
};
Interfaces.ListNode = function (face, next){
this.next = next;
this.face = face;
return this;
};
Interfaces.List.prototype.addFace = function (face){
face.id = this.index;
if (this.size){
var curr = this.head;
while (curr.next){
curr = curr.next;
}
curr.next = new Interfaces.ListNode(face, null);
} else {
this.head = new Interfaces.ListNode(face, null);
}
this.size++;
this.index++;
return face.id;
};
Interfaces.List.prototype.removeFace = function(id){
var curr = this.head;
while (curr && curr.next && (curr.next.face.id < id)){
curr = curr.next;
}
if (curr.face.id === id){
curr.next = curr.next.next;
this.size--;
}
};
Interfaces.List.prototype.dispatchByIds = function (idArray, buffer){
var id, curr = this.head;
while (idArray.length){
id = idArray.pop();
while (curr && curr.face.id < id){
curr = curr.next;
}
if (curr && curr.face.id === id){
curr.face.send(buffer);
}
}
};
Interfaces.List.prototype.get = function(id){
var curr = this.head;
while(curr && curr.face && curr.face.id < id){
curr = curr.next;
}
if (curr && curr.face && curr.face.id === id){
return curr.face;
} else {
return null;
}
};
/**Install a transport Class to the Interfaces manager. If the Class has a Listener function, the Listener will be invoked
*@param {Transport} Transport a Transport Class matching the Abstract Transport API
*@returns {Interfaces} for chaining
*/
Interfaces.prototype.installTransport = function(Transport){
this.transports[Transport.prototype.name] = Transport;
if (Transport.Listener){
Transport.Listener(this);
}
return this;
};
/**Create a new Face
*@param {String} protocol a string matching the .protocolKey property of a previously installed {@link Transport}
*@param {Object} connectionParameters the object expected by the transport class
*@returns {Number} id the numerical faceID of the created Face.
*/
Interfaces.prototype.newFace = function(protocol, connectionParameters, onopen, onclose) {
var Self = this;
if (!this.transports[protocol]){
return -1;
} else {
var Transport = new this.transports[protocol](connectionParameters)
, newFace = new ndn.Face(Transport, Transport.connectionInfo);
this.Faces.addFace(newFace);
var connectionInfo;
if (protocol === "WebSocketTransport"){
connectionInfo = new this.transports[protocol].ConnectionInfo(connectionParameters.host, connectionParameters.port);
} else {
connectionInfo = newFace.connectionInfo || Transport.connectionInfo ||new this.transports[protocol].ConnectionInfo(Transport.socket);
}
if (onclose){
newFace.onclose = onclose;
}
newFace.transport.connect(connectionInfo, newFace, function(){
newFace.onReceivedElement = function(element){
var decoder = new TlvDecoder(element);
if (decoder.peekType(Tlv.Interest, element.length)) {
Self.subject.handleInterest(element, this.id);
}
else if (decoder.peekType(Tlv.Data, element.length)) {
Self.subject.handleData(element, this.id);
}
};
newFace.send = function(element){
this.transport.send(element);
};
if (onopen) {
onopen(newFace.id);
}
}, function(){
//onclose event TODO
if (onclose) {
onclose(newFace.id);
}
});
return newFace.id;
}
};
Interfaces.prototype.closeFace = function(){};
/** Dispatch an element to one or more Faces
*@param {Buffer} element the raw packet to dispatch
*@param {Number} faceFlag an Integer representing the faces to send one
*@param {Function} callback called per face sent, used for testing
*@returns {Interfaces} for chaining
*/
Interfaces.prototype.dispatch = function(element, faceIDs, callback){
this.Faces.dispatchByIds(faceIDs, element);
return this;
};
module.exports = Interfaces;