UNPKG

ndn-io

Version:

NDN I/O module for node.js and the browser

198 lines (175 loc) 5.96 kB
var ndn , contrib , debug = require("debug")("Publisher"); if (!File){ var File = function File(){} , Blob = function Blob(){}; } /** Publisher object *@constructor *@param {IO} io the IO instance *@param {String=} name the uri to publish the object as *@param {File|Blob|Buffer|FilePath|String|Object=} toPublish the thing to publish *@param {Number=} freshnessPeriod the freshnessPeriod of the published data in milliseconds (default 1 hour) *@returns {Publisher} */ function Publisher (io, name, toPublish, freshnessPeriod){ debug("constructor"); this.contentStore = io.contentStore; this.toPublish = toPublish || null; this.name = (name) ? new ndn.Name(name) : null; this.freshnessPeriod = freshnessPeriod || 60 * 60 * 1000; return this; } /** import ndn-contrib into Class scope *@static *@param {Object} NDN the ndn-contrib object */ Publisher.installContrib = function(contrib){ contrib = contrib; ndn = contrib.ndn; }; /** set the freshnessPeriod of data to publish *@param {Number} milliseconds freshness period of published packets *@returns {this} for chaining */ Publisher.prototype.setFreshnessPeriod = function(milliseconds){ debug("set freshness milliseconds to %s", milliseconds); this.freshnessPeriod = milliseconds; return this; }; /** set the thing to publish *@oaram {File|Blob|Buffer|FilePath|String|Object} toPublish the thing to publish *@returns {this} this for chaining */ Publisher.prototype.setToPublish = function(toPublish){ var er; if (typeof toPublish !== "string") { debug("toPublish not a string"); if (!(toPublish instanceof File || (toPublish instanceof Blob) || (toPublish instanceof Buffer) || (toPublish instanceof Object) )){ er = true; } else if (toPublish instanceof Object){ try{ JSON.stringify(toPublish); } catch (e){ er = e; } } if (er) { throw new TypeError("toPublish must be File, Blob, Buffer, FilePath, String, or parsable JSON"); } } this.toPublish = toPublish; return this; }; /** set the name to publish *@oaram {String} name the uri to publish as *@returns {this} this for chaining */ Publisher.prototype.setName = function(name){ this.name = new ndn.Name(name); debug("set Name", this.name.toUri()); return this; }; /** publish the data *@param {Function=} callback *@returns {this} this for chaining */ Publisher.prototype.publish = function(callback){ callback = callback || function(){}; if (((this.toPublish.type && this.toPublish.size && this.toPublish.name) || (this.toPublish instanceof Blob) || (Buffer.isBuffer(this.toPublish))) || ((typeof this.toPublish === "string") && (this.toPublish.indexOf("file://") === 0))){ this.publishFile(callback); } else if (typeof this.toPublish === "string"){ callback(this.publishString()); } else if (typeof this.toPublish === "object"){ callback(this.publishJSON()); } return this; }; /** read a file, Buffer, Blob, or Filepath into a buffer *@private *@param {File|Blob|Buffer|FilePath} file a handle to the file/blob/buffer *@returns {Buffer} */ Publisher.prototype.readFile = require("./node/readFile.js"); /** read, chunk, name, sign, encode, insert into contentStore *@private *@returns {Object} firstData the ndn.Data packet of the first content Object, signed and marked with final */ Publisher.prototype.publishFile = function(callback){ debug("publishfile called for %s", this.name.toUri()); var Self = this; var name = Self.name; this.readFile(this.toPublish, function(buffer){ debug("file read to buffer"); var length = Math.ceil(buffer.length / 8000) , firstData; for (var i = 0; i < length; i++){ var n = new ndn.Name(name); n.appendSegment(i); var chunk = buffer.slice(i * 8000, (i + 1) * 8000) , d = new ndn.Data(n, new ndn.SignedInfo(), chunk); d.signedInfo.setFreshnessPeriod(Self.freshnessPeriod); if (length > 1){ d.signedInfo.setFinalBlockID(new ndn.Name.Component(ndn.DataUtils.nonNegativeIntToBigEndian(length - 1))); } else { d.signedInfo.setFinalBlockID(n.get(-1)); } debug("inserting %s into contentStore", d.name.toUri()); Self.contentStore.insert(d.wireEncode().buffer, d); if (i === 0){ firstData = d; } } callback(firstData); }); }; /** stringify and call Pubisher.publishString *@private *@returns {Object} firstData the ndn.Data packet of the first content Object, signed and marked with final */ Publisher.prototype.publishJSON = function(){ debug("publishJSON %s", this.name.toUri()); return this.setToPublish(JSON.stringify(this.toPublish)) .publishString(); }; /** chunk, name, sign, encode, insert into contentStore *@private *@returns {Object} firstData the ndn.Data packet of the first content Object, signed and marked with final */ Publisher.prototype.publishString = function(){ var chunks = [] , firstData; debug("publishString %", this.name.toUri()); while (this.toPublish.length > 0){ chunks.push(this.toPublish.substr(0,8000)); this.toPublish = this.toPublish.substr(8000, this.toPublish.length); } var length = chunks.length; for (var i = 0; i < length; i++){ var n = new ndn.Name(this.name); var d = new ndn.Data(n.appendSegment(i), new ndn.SignedInfo(), chunks.shift()); d.signedInfo.setFreshnessPeriod(this.freshnessPeriod); if (length === 0){ d.signedInfo.setFinalBlockID(n.get(-1)); } else{ d.signedInfo.setFinalBlockID(new ndn.Name.Component(ndn.DataUtils.nonNegativeIntToBigEndian(length - 1))); } d.sign(); debug("inserting %s into contentStore", d.name.toUri()); this.contentStore.insert(d.wireEncode().buffer, d); if (i === 0){ firstData = d; } } return firstData; }; module.exports = Publisher;