Source: encoding/tlv-0_2-wire-format.js

  1. /**
  2. * Copyright (C) 2013-2018 Regents of the University of California.
  3. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. * A copy of the GNU Lesser General Public License is in the file COPYING.
  18. */
  19. /** @ignore */
  20. var Crypto = require('../crypto.js'); /** @ignore */
  21. var Blob = require('../util/blob.js').Blob; /** @ignore */
  22. var Name = require('../name.js').Name; /** @ignore */
  23. var ComponentType = require('../name.js').ComponentType; /** @ignore */
  24. var ForwardingFlags = require('../forwarding-flags').ForwardingFlags; /** @ignore */
  25. var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
  26. var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
  27. var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
  28. var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
  29. var Exclude = require('../exclude.js').Exclude; /** @ignore */
  30. var ContentType = require('../meta-info.js').ContentType; /** @ignore */
  31. var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
  32. var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
  33. var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
  34. var GenericSignature = require('../generic-signature.js').GenericSignature; /** @ignore */
  35. var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
  36. var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
  37. var ControlParameters = require('../control-parameters.js').ControlParameters; /** @ignore */
  38. var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
  39. var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
  40. var Schedule = require('../encrypt/schedule.js').Schedule; /** @ignore */
  41. var IncomingFaceId = require('../lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
  42. var CongestionMark = require('../lp/congestion-mark.js').CongestionMark; /** @ignore */
  43. var DecodingException = require('./decoding-exception.js').DecodingException;
  44. /**
  45. * A Tlv0_2WireFormat implements the WireFormat interface for encoding and
  46. * decoding with the NDN-TLV wire format, version 0.2.
  47. * @constructor
  48. */
  49. var Tlv0_2WireFormat = function Tlv0_2WireFormat()
  50. {
  51. // Inherit from WireFormat.
  52. WireFormat.call(this);
  53. };
  54. Tlv0_2WireFormat.prototype = new WireFormat();
  55. Tlv0_2WireFormat.prototype.name = "Tlv0_2WireFormat";
  56. exports.Tlv0_2WireFormat = Tlv0_2WireFormat;
  57. // Default object.
  58. Tlv0_2WireFormat.instance = null;
  59. /**
  60. * Encode name as an NDN-TLV Name and return the encoding.
  61. * @param {Name} name The Name to encode.
  62. * @return {Blobl} A Blob containing the encoding.
  63. */
  64. Tlv0_2WireFormat.prototype.encodeName = function(name)
  65. {
  66. var encoder = new TlvEncoder();
  67. Tlv0_2WireFormat.encodeName(name, encoder);
  68. return new Blob(encoder.getOutput(), false);
  69. };
  70. /**
  71. * Decode input as a NDN-TLV name and set the fields of the Name object.
  72. * @param {Name} name The Name object whose fields are updated.
  73. * @param {Buffer} input The buffer with the bytes to decode.
  74. * @param {boolean} copy (optional) If true, copy from the input when making new
  75. * Blob values. If false, then Blob values share memory with the input, which
  76. * must remain unchanged while the Blob values are used. If omitted, use true.
  77. */
  78. Tlv0_2WireFormat.prototype.decodeName = function(name, input, copy)
  79. {
  80. if (copy == null)
  81. copy = true;
  82. var decoder = new TlvDecoder(input);
  83. Tlv0_2WireFormat.decodeName(name, decoder, copy);
  84. };
  85. /**
  86. * Encode the interest using NDN-TLV and return a Buffer.
  87. * @param {Interest} interest The Interest object to encode.
  88. * @return {object} An associative array with fields
  89. * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
  90. * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
  91. * the encoding of the beginning of the signed portion, and
  92. * signedPortionEndOffset is the offset in the encoding of the end of the signed
  93. * portion. The signed portion starts from the first name component and ends
  94. * just before the final name component (which is assumed to be a signature for
  95. * a signed interest).
  96. */
  97. Tlv0_2WireFormat.prototype.encodeInterest = function(interest)
  98. {
  99. var encoder = new TlvEncoder(256);
  100. var saveLength = encoder.getLength();
  101. // Encode backwards.
  102. if (interest.getForwardingHint().size() > 0) {
  103. if (interest.getSelectedDelegationIndex() != null)
  104. throw new Error
  105. ("An Interest may not have a selected delegation when encoding a forwarding hint");
  106. if (interest.hasLink())
  107. throw new Error
  108. ("An Interest may not have a link object when encoding a forwarding hint");
  109. var forwardingHintSaveLength = encoder.getLength();
  110. Tlv0_2WireFormat.encodeDelegationSet_(interest.getForwardingHint(), encoder);
  111. encoder.writeTypeAndLength(
  112. Tlv.ForwardingHint, encoder.getLength() - forwardingHintSaveLength);
  113. }
  114. encoder.writeOptionalNonNegativeIntegerTlv
  115. (Tlv.SelectedDelegation, interest.getSelectedDelegationIndex());
  116. var linkWireEncoding = interest.getLinkWireEncoding(this);
  117. if (!linkWireEncoding.isNull())
  118. // Encode the entire link as is.
  119. encoder.writeBuffer(linkWireEncoding.buf());
  120. encoder.writeOptionalNonNegativeIntegerTlv
  121. (Tlv.InterestLifetime, interest.getInterestLifetimeMilliseconds());
  122. // Encode the Nonce as 4 bytes.
  123. if (interest.getNonce().isNull() || interest.getNonce().size() == 0)
  124. // This is the most common case. Generate a nonce.
  125. encoder.writeBlobTlv(Tlv.Nonce, Crypto.randomBytes(4));
  126. else if (interest.getNonce().size() < 4) {
  127. var nonce = Buffer(4);
  128. // Copy existing nonce bytes.
  129. interest.getNonce().buf().copy(nonce);
  130. // Generate random bytes for remaining bytes in the nonce.
  131. for (var i = interest.getNonce().size(); i < 4; ++i)
  132. nonce[i] = Crypto.randomBytes(1)[0];
  133. encoder.writeBlobTlv(Tlv.Nonce, nonce);
  134. }
  135. else if (interest.getNonce().size() == 4)
  136. // Use the nonce as-is.
  137. encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf());
  138. else
  139. // Truncate.
  140. encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf().slice(0, 4));
  141. Tlv0_2WireFormat.encodeSelectors(interest, encoder);
  142. var tempOffsets = Tlv0_2WireFormat.encodeName(interest.getName(), encoder);
  143. var signedPortionBeginOffsetFromBack =
  144. encoder.getLength() - tempOffsets.signedPortionBeginOffset;
  145. var signedPortionEndOffsetFromBack =
  146. encoder.getLength() - tempOffsets.signedPortionEndOffset;
  147. encoder.writeTypeAndLength(Tlv.Interest, encoder.getLength() - saveLength);
  148. var signedPortionBeginOffset =
  149. encoder.getLength() - signedPortionBeginOffsetFromBack;
  150. var signedPortionEndOffset =
  151. encoder.getLength() - signedPortionEndOffsetFromBack;
  152. return { encoding: new Blob(encoder.getOutput(), false),
  153. signedPortionBeginOffset: signedPortionBeginOffset,
  154. signedPortionEndOffset: signedPortionEndOffset };
  155. };
  156. /**
  157. * Decode input as an NDN-TLV interest and set the fields of the interest
  158. * object.
  159. * @param {Interest} interest The Interest object whose fields are updated.
  160. * @param {Buffer} input The buffer with the bytes to decode.
  161. * @param {boolean} copy (optional) If true, copy from the input when making new
  162. * Blob values. If false, then Blob values share memory with the input, which
  163. * must remain unchanged while the Blob values are used. If omitted, use true.
  164. * @return {object} An associative array with fields
  165. * (signedPortionBeginOffset, signedPortionEndOffset) where
  166. * signedPortionBeginOffset is the offset in the encoding of the beginning of
  167. * the signed portion, and signedPortionEndOffset is the offset in the encoding
  168. * of the end of the signed portion. The signed portion starts from the first
  169. * name component and ends just before the final name component (which is
  170. * assumed to be a signature for a signed interest).
  171. */
  172. Tlv0_2WireFormat.prototype.decodeInterest = function(interest, input, copy)
  173. {
  174. try {
  175. return this.decodeInterestV02_(interest, input, copy);
  176. } catch (exceptionV02) {
  177. try {
  178. // Failed to decode as format v0.2. Try to decode as v0.3.
  179. return Tlv0_2WireFormat.decodeInterestV03_(interest, input, copy);
  180. } catch (ex) {
  181. // Ignore the exception decoding as format v0.3 and throw the exception
  182. // from trying to decode as format as format v0.2.
  183. throw exceptionV02;
  184. }
  185. }
  186. };
  187. /**
  188. * Do the work of decodeInterest to decode strictly as format v0.2.
  189. */
  190. Tlv0_2WireFormat.prototype.decodeInterestV02_ = function(interest, input, copy)
  191. {
  192. if (copy == null)
  193. copy = true;
  194. var decoder = new TlvDecoder(input);
  195. var endOffset = decoder.readNestedTlvsStart(Tlv.Interest);
  196. var offsets = Tlv0_2WireFormat.decodeName(interest.getName(), decoder, copy);
  197. if (decoder.peekType(Tlv.Selectors, endOffset))
  198. Tlv0_2WireFormat.decodeSelectors(interest, decoder, copy);
  199. else {
  200. // Set selectors to none.
  201. interest.setMinSuffixComponents(null);
  202. interest.setMaxSuffixComponents(null);
  203. interest.getKeyLocator().clear();
  204. interest.getExclude().clear();
  205. interest.setChildSelector(null);
  206. interest.setMustBeFresh(false);
  207. }
  208. // Require a Nonce, but don't force it to be 4 bytes.
  209. var nonce = decoder.readBlobTlv(Tlv.Nonce);
  210. interest.setInterestLifetimeMilliseconds
  211. (decoder.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime, endOffset));
  212. if (decoder.peekType(Tlv.ForwardingHint, endOffset)) {
  213. var forwardingHintEndOffset = decoder.readNestedTlvsStart
  214. (Tlv.ForwardingHint);
  215. Tlv0_2WireFormat.decodeDelegationSet_
  216. (interest.getForwardingHint(), forwardingHintEndOffset, decoder, copy);
  217. decoder.finishNestedTlvs(forwardingHintEndOffset);
  218. }
  219. if (decoder.peekType(Tlv.Data, endOffset)) {
  220. // Get the bytes of the Link TLV.
  221. var linkBeginOffset = decoder.getOffset();
  222. var linkEndOffset = decoder.readNestedTlvsStart(Tlv.Data);
  223. decoder.seek(linkEndOffset);
  224. interest.setLinkWireEncoding
  225. (new Blob(decoder.getSlice(linkBeginOffset, linkEndOffset), copy), this);
  226. }
  227. else
  228. interest.unsetLink();
  229. interest.setSelectedDelegationIndex
  230. (decoder.readOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation, endOffset));
  231. if (interest.getSelectedDelegationIndex() != null &&
  232. interest.getSelectedDelegationIndex() >= 0 && !interest.hasLink())
  233. throw new Error("Interest has a selected delegation, but no link object");
  234. // Set the nonce last because setting other interest fields clears it.
  235. interest.setNonce(new Blob(nonce, copy));
  236. decoder.finishNestedTlvs(endOffset);
  237. return offsets;
  238. };
  239. /**
  240. * Encode data as NDN-TLV and return the encoding and signed offsets.
  241. * @param {Data} data The Data object to encode.
  242. * @return {object} An associative array with fields
  243. * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
  244. * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
  245. * the encoding of the beginning of the signed portion, and
  246. * signedPortionEndOffset is the offset in the encoding of the end of the
  247. * signed portion.
  248. */
  249. Tlv0_2WireFormat.prototype.encodeData = function(data)
  250. {
  251. var encoder = new TlvEncoder(1500);
  252. var saveLength = encoder.getLength();
  253. // Encode backwards.
  254. encoder.writeBlobTlv(Tlv.SignatureValue, data.getSignature().getSignature().buf());
  255. var signedPortionEndOffsetFromBack = encoder.getLength();
  256. Tlv0_2WireFormat.encodeSignatureInfo_(data.getSignature(), encoder);
  257. encoder.writeBlobTlv(Tlv.Content, data.getContent().buf());
  258. Tlv0_2WireFormat.encodeMetaInfo(data.getMetaInfo(), encoder);
  259. Tlv0_2WireFormat.encodeName(data.getName(), encoder);
  260. var signedPortionBeginOffsetFromBack = encoder.getLength();
  261. encoder.writeTypeAndLength(Tlv.Data, encoder.getLength() - saveLength);
  262. var signedPortionBeginOffset =
  263. encoder.getLength() - signedPortionBeginOffsetFromBack;
  264. var signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
  265. return { encoding: new Blob(encoder.getOutput(), false),
  266. signedPortionBeginOffset: signedPortionBeginOffset,
  267. signedPortionEndOffset: signedPortionEndOffset };
  268. };
  269. /**
  270. * Decode input as an NDN-TLV data packet, set the fields in the data object,
  271. * and return the signed offsets.
  272. * @param {Data} data The Data object whose fields are updated.
  273. * @param {Buffer} input The buffer with the bytes to decode.
  274. * @param {boolean} copy (optional) If true, copy from the input when making new
  275. * Blob values. If false, then Blob values share memory with the input, which
  276. * must remain unchanged while the Blob values are used. If omitted, use true.
  277. * @return {object} An associative array with fields
  278. * (signedPortionBeginOffset, signedPortionEndOffset) where
  279. * signedPortionBeginOffset is the offset in the encoding of the beginning of
  280. * the signed portion, and signedPortionEndOffset is the offset in the encoding
  281. * of the end of the signed portion.
  282. */
  283. Tlv0_2WireFormat.prototype.decodeData = function(data, input, copy)
  284. {
  285. if (copy == null)
  286. copy = true;
  287. var decoder = new TlvDecoder(input);
  288. var endOffset = decoder.readNestedTlvsStart(Tlv.Data);
  289. var signedPortionBeginOffset = decoder.getOffset();
  290. Tlv0_2WireFormat.decodeName(data.getName(), decoder, copy);
  291. Tlv0_2WireFormat.decodeMetaInfo(data.getMetaInfo(), decoder, copy);
  292. data.setContent(new Blob(decoder.readBlobTlv(Tlv.Content), copy));
  293. Tlv0_2WireFormat.decodeSignatureInfo(data, decoder, copy);
  294. var signedPortionEndOffset = decoder.getOffset();
  295. data.getSignature().setSignature
  296. (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));
  297. decoder.finishNestedTlvs(endOffset);
  298. return { signedPortionBeginOffset: signedPortionBeginOffset,
  299. signedPortionEndOffset: signedPortionEndOffset };
  300. };
  301. /**
  302. * Encode controlParameters as NDN-TLV and return the encoding.
  303. * @param {ControlParameters} controlParameters The ControlParameters object to
  304. * encode.
  305. * @return {Blob} A Blob containing the encoding.
  306. */
  307. Tlv0_2WireFormat.prototype.encodeControlParameters = function(controlParameters)
  308. {
  309. var encoder = new TlvEncoder(256);
  310. Tlv0_2WireFormat.encodeControlParameters(controlParameters, encoder);
  311. return new Blob(encoder.getOutput(), false);
  312. };
  313. /**
  314. * Decode controlParameters in NDN-TLV and set the fields of the
  315. * controlParameters object.
  316. * @param {ControlParameters} controlParameters The ControlParameters object
  317. * whose fields are updated.
  318. * @param {Buffer} input The buffer with the bytes to decode.
  319. * @param {boolean} copy (optional) If true, copy from the input when making new
  320. * Blob values. If false, then Blob values share memory with the input, which
  321. * must remain unchanged while the Blob values are used. If omitted, use true.
  322. * @throws DecodingException For invalid encoding
  323. */
  324. Tlv0_2WireFormat.prototype.decodeControlParameters = function
  325. (controlParameters, input, copy)
  326. {
  327. if (copy == null)
  328. copy = true;
  329. var decoder = new TlvDecoder(input);
  330. Tlv0_2WireFormat.decodeControlParameters(controlParameters, decoder, copy);
  331. };
  332. /**
  333. * Encode controlResponse as NDN-TLV and return the encoding.
  334. * @param {ControlResponse} controlResponse The ControlResponse object to
  335. * encode.
  336. * @return {Blob} A Blob containing the encoding.
  337. */
  338. Tlv0_2WireFormat.prototype.encodeControlResponse = function(controlResponse)
  339. {
  340. var encoder = new TlvEncoder(256);
  341. var saveLength = encoder.getLength();
  342. // Encode backwards.
  343. // Encode the body.
  344. if (controlResponse.getBodyAsControlParameters() != null)
  345. Tlv0_2WireFormat.encodeControlParameters
  346. (controlResponse.getBodyAsControlParameters(), encoder);
  347. encoder.writeBlobTlv
  348. (Tlv.NfdCommand_StatusText, new Blob(controlResponse.getStatusText()).buf());
  349. encoder.writeNonNegativeIntegerTlv
  350. (Tlv.NfdCommand_StatusCode, controlResponse.getStatusCode());
  351. encoder.writeTypeAndLength
  352. (Tlv.NfdCommand_ControlResponse, encoder.getLength() - saveLength);
  353. return new Blob(encoder.getOutput(), false);
  354. };
  355. /**
  356. * Decode controlResponse in NDN-TLV and set the fields of the controlResponse
  357. * object
  358. * @param {ControlResponse} controlResponse The ControlResponse object whose
  359. * fields are updated.
  360. * @param {Buffer} input The buffer with the bytes to decode.
  361. * @param {boolean} copy (optional) If true, copy from the input when making new
  362. * Blob values. If false, then Blob values share memory with the input, which
  363. * must remain unchanged while the Blob values are used. If omitted, use true.
  364. * @throws DecodingException For invalid encoding
  365. */
  366. Tlv0_2WireFormat.prototype.decodeControlResponse = function
  367. (controlResponse, input, copy)
  368. {
  369. if (copy == null)
  370. copy = true;
  371. var decoder = new TlvDecoder(input);
  372. var endOffset = decoder.readNestedTlvsStart(Tlv.NfdCommand_ControlResponse);
  373. controlResponse.setStatusCode(decoder.readNonNegativeIntegerTlv
  374. (Tlv.NfdCommand_StatusCode));
  375. // Set copy false since we just immediately get a string.
  376. var statusText = new Blob
  377. (decoder.readBlobTlv(Tlv.NfdCommand_StatusText), false);
  378. controlResponse.setStatusText(statusText.toString());
  379. // Decode the body.
  380. if (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
  381. controlResponse.setBodyAsControlParameters(new ControlParameters());
  382. // Decode into the existing ControlParameters to avoid copying.
  383. Tlv0_2WireFormat.decodeControlParameters
  384. (controlResponse.getBodyAsControlParameters(), decoder, copy);
  385. }
  386. else
  387. controlResponse.setBodyAsControlParameters(null);
  388. decoder.finishNestedTlvs(endOffset);
  389. };
  390. /**
  391. * Encode signature as an NDN-TLV SignatureInfo and return the encoding.
  392. * @param {Signature} signature An object of a subclass of Signature to encode.
  393. * @return {Blob} A Blob containing the encoding.
  394. */
  395. Tlv0_2WireFormat.prototype.encodeSignatureInfo = function(signature)
  396. {
  397. var encoder = new TlvEncoder(256);
  398. Tlv0_2WireFormat.encodeSignatureInfo_(signature, encoder);
  399. return new Blob(encoder.getOutput(), false);
  400. };
  401. // SignatureHolder is used by decodeSignatureInfoAndValue.
  402. Tlv0_2WireFormat.SignatureHolder = function Tlv0_2WireFormatSignatureHolder()
  403. {
  404. };
  405. Tlv0_2WireFormat.SignatureHolder.prototype.setSignature = function(signature)
  406. {
  407. this.signature = signature;
  408. };
  409. Tlv0_2WireFormat.SignatureHolder.prototype.getSignature = function()
  410. {
  411. return this.signature;
  412. };
  413. /**
  414. * Decode signatureInfo as an NDN-TLV SignatureInfo and signatureValue as the
  415. * related SignatureValue, and return a new object which is a subclass of Signature.
  416. * @param {Buffer} signatureInfo The buffer with the signature info bytes to
  417. * decode.
  418. * @param {Buffer} signatureValue The buffer with the signature value to decode.
  419. * @param {boolean} copy (optional) If true, copy from the input when making new
  420. * Blob values. If false, then Blob values share memory with the input, which
  421. * must remain unchanged while the Blob values are used. If omitted, use true.
  422. * @return {Signature} A new object which is a subclass of Signature.
  423. */
  424. Tlv0_2WireFormat.prototype.decodeSignatureInfoAndValue = function
  425. (signatureInfo, signatureValue, copy)
  426. {
  427. if (copy == null)
  428. copy = true;
  429. // Use a SignatureHolder to imitate a Data object for decodeSignatureInfo.
  430. var signatureHolder = new Tlv0_2WireFormat.SignatureHolder();
  431. var decoder = new TlvDecoder(signatureInfo);
  432. Tlv0_2WireFormat.decodeSignatureInfo(signatureHolder, decoder, copy);
  433. decoder = new TlvDecoder(signatureValue);
  434. signatureHolder.getSignature().setSignature
  435. (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));
  436. return signatureHolder.getSignature();
  437. };
  438. /**
  439. * Encode the signatureValue in the Signature object as an NDN-TLV
  440. * SignatureValue (the signature bits) and return the encoding.
  441. * @param {Signature} signature An object of a subclass of Signature with the
  442. * signature value to encode.
  443. * @return {Blob} A Blob containing the encoding.
  444. */
  445. Tlv0_2WireFormat.prototype.encodeSignatureValue = function(signature)
  446. {
  447. var encoder = new TlvEncoder(256);
  448. encoder.writeBlobTlv(Tlv.SignatureValue, signature.getSignature().buf());
  449. return new Blob(encoder.getOutput(), false);
  450. };
  451. /**
  452. * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
  453. * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
  454. * @param {Buffer} input The buffer with the bytes to decode.
  455. * @param {boolean} copy (optional) If true, copy from the input when making new
  456. * Blob values. If false, then Blob values share memory with the input, which
  457. * must remain unchanged while the Blob values are used. If omitted, use true.
  458. */
  459. Tlv0_2WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
  460. {
  461. if (copy == null)
  462. copy = true;
  463. lpPacket.clear();
  464. var decoder = new TlvDecoder(input);
  465. var endOffset = decoder.readNestedTlvsStart(Tlv.LpPacket_LpPacket);
  466. while (decoder.getOffset() < endOffset) {
  467. // Imitate TlvDecoder.readTypeAndLength.
  468. var fieldType = decoder.readVarNumber();
  469. var fieldLength = decoder.readVarNumber();
  470. var fieldEndOffset = decoder.getOffset() + fieldLength;
  471. if (fieldEndOffset > input.length)
  472. throw new DecodingException(new Error("TLV length exceeds the buffer length"));
  473. if (fieldType == Tlv.LpPacket_Fragment) {
  474. // Set the fragment to the bytes of the TLV value.
  475. lpPacket.setFragmentWireEncoding
  476. (new Blob(decoder.getSlice(decoder.getOffset(), fieldEndOffset), copy));
  477. decoder.seek(fieldEndOffset);
  478. // The fragment is supposed to be the last field.
  479. break;
  480. }
  481. else if (fieldType == Tlv.LpPacket_Nack) {
  482. var networkNack = new NetworkNack();
  483. var code = decoder.readOptionalNonNegativeIntegerTlv
  484. (Tlv.LpPacket_NackReason, fieldEndOffset);
  485. var reason;
  486. // The enum numeric values are the same as this wire format, so use as is.
  487. if (code < 0 || code == NetworkNack.Reason.NONE)
  488. // This includes an omitted NackReason.
  489. networkNack.setReason(NetworkNack.Reason.NONE);
  490. else if (code == NetworkNack.Reason.CONGESTION ||
  491. code == NetworkNack.Reason.DUPLICATE ||
  492. code == NetworkNack.Reason.NO_ROUTE)
  493. networkNack.setReason(code);
  494. else {
  495. // Unrecognized reason.
  496. networkNack.setReason(NetworkNack.Reason.OTHER_CODE);
  497. networkNack.setOtherReasonCode(code);
  498. }
  499. lpPacket.addHeaderField(networkNack);
  500. }
  501. else if (fieldType == Tlv.LpPacket_IncomingFaceId) {
  502. var incomingFaceId = new IncomingFaceId();
  503. incomingFaceId.setFaceId(decoder.readNonNegativeInteger(fieldLength));
  504. lpPacket.addHeaderField(incomingFaceId);
  505. }
  506. else if (fieldType == Tlv.LpPacket_CongestionMark) {
  507. var congestionMark = new CongestionMark();
  508. congestionMark.setCongestionMark(decoder.readNonNegativeInteger
  509. (fieldLength));
  510. lpPacket.addHeaderField(congestionMark);
  511. }
  512. else {
  513. // Unrecognized field type. The conditions for ignoring are here:
  514. // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
  515. var canIgnore =
  516. (fieldType >= Tlv.LpPacket_IGNORE_MIN &&
  517. fieldType <= Tlv.LpPacket_IGNORE_MAX &&
  518. (fieldType & 0x03) == 0);
  519. if (!canIgnore)
  520. throw new DecodingException(new Error("Did not get the expected TLV type"));
  521. // Ignore.
  522. decoder.seek(fieldEndOffset);
  523. }
  524. decoder.finishNestedTlvs(fieldEndOffset);
  525. }
  526. decoder.finishNestedTlvs(endOffset);
  527. };
  528. /**
  529. * Encode delegationSet as a sequence of NDN-TLV Delegation, and return the
  530. * encoding. Note that the sequence of Delegation does not have an outer TLV
  531. * type and length because it is intended to use the type and length of a Data
  532. * packet's Content.
  533. * @param {DelegationSet} delegationSet The DelegationSet object to encode.
  534. * @return {Blob} A Blob containing the encoding.
  535. */
  536. Tlv0_2WireFormat.prototype.encodeDelegationSet = function(delegationSet)
  537. {
  538. var encoder = new TlvEncoder(256);
  539. Tlv0_2WireFormat.encodeDelegationSet_(delegationSet, encoder);
  540. return new Blob(encoder.getOutput(), false);
  541. };
  542. /**
  543. * Decode input as a sequence of NDN-TLV Delegation and set the fields of the
  544. * delegationSet object. Note that the sequence of Delegation does not have an
  545. * outer TLV type and length because it is intended to use the type and length
  546. * of a Data packet's Content. This ignores any elements after the sequence
  547. * of Delegation.
  548. * @param {DelegationSet} delegationSet The DelegationSet object
  549. * whose fields are updated.
  550. * @param {Buffer} input The buffer with the bytes to decode.
  551. * @param {boolean} copy (optional) If true, copy from the input when making new
  552. * Blob values. If false, then Blob values share memory with the input, which
  553. * must remain unchanged while the Blob values are used. If omitted, use true.
  554. */
  555. Tlv0_2WireFormat.prototype.decodeDelegationSet = function
  556. (delegationSet, input, copy)
  557. {
  558. if (copy == null)
  559. copy = true;
  560. var decoder = new TlvDecoder(input);
  561. Tlv0_2WireFormat.decodeDelegationSet_
  562. (delegationSet, input.length, decoder, copy);
  563. };
  564. /**
  565. * Encode the EncryptedContent in NDN-TLV and return the encoding.
  566. * @param {EncryptedContent} encryptedContent The EncryptedContent object to
  567. * encode.
  568. * @return {Blob} A Blob containing the encoding.
  569. */
  570. Tlv0_2WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
  571. {
  572. var encoder = new TlvEncoder(256);
  573. var saveLength = encoder.getLength();
  574. // Encode backwards.
  575. encoder.writeBlobTlv
  576. (Tlv.Encrypt_EncryptedPayload, encryptedContent.getPayload().buf());
  577. encoder.writeOptionalBlobTlv
  578. (Tlv.Encrypt_InitialVector, encryptedContent.getInitialVector().buf());
  579. // Assume the algorithmType value is the same as the TLV type.
  580. encoder.writeNonNegativeIntegerTlv
  581. (Tlv.Encrypt_EncryptionAlgorithm, encryptedContent.getAlgorithmType());
  582. Tlv0_2WireFormat.encodeKeyLocator
  583. (Tlv.KeyLocator, encryptedContent.getKeyLocator(), encoder);
  584. encoder.writeTypeAndLength
  585. (Tlv.Encrypt_EncryptedContent, encoder.getLength() - saveLength);
  586. return new Blob(encoder.getOutput(), false);
  587. };
  588. /**
  589. * Decode input as an EncryptedContent in NDN-TLV and set the fields of the
  590. * encryptedContent object.
  591. * @param {EncryptedContent} encryptedContent The EncryptedContent object
  592. * whose fields are updated.
  593. * @param {Buffer} input The buffer with the bytes to decode.
  594. * @param {boolean} copy (optional) If true, copy from the input when making new
  595. * Blob values. If false, then Blob values share memory with the input, which
  596. * must remain unchanged while the Blob values are used. If omitted, use true.
  597. */
  598. Tlv0_2WireFormat.prototype.decodeEncryptedContent = function
  599. (encryptedContent, input, copy)
  600. {
  601. if (copy == null)
  602. copy = true;
  603. var decoder = new TlvDecoder(input);
  604. var endOffset = decoder.
  605. readNestedTlvsStart(Tlv.Encrypt_EncryptedContent);
  606. Tlv0_2WireFormat.decodeKeyLocator
  607. (Tlv.KeyLocator, encryptedContent.getKeyLocator(), decoder, copy);
  608. encryptedContent.setAlgorithmType
  609. (decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm));
  610. encryptedContent.setInitialVector
  611. (new Blob(decoder.readOptionalBlobTlv
  612. (Tlv.Encrypt_InitialVector, endOffset), copy));
  613. encryptedContent.setPayload
  614. (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EncryptedPayload), copy));
  615. decoder.finishNestedTlvs(endOffset);
  616. };
  617. /**
  618. * Get a singleton instance of a Tlv0_2WireFormat. To always use the
  619. * preferred version NDN-TLV, you should use TlvWireFormat.get().
  620. * @return {Tlv0_2WireFormat} The singleton instance.
  621. */
  622. Tlv0_2WireFormat.get = function()
  623. {
  624. if (Tlv0_2WireFormat.instance === null)
  625. Tlv0_2WireFormat.instance = new Tlv0_2WireFormat();
  626. return Tlv0_2WireFormat.instance;
  627. };
  628. /**
  629. * Encode the name component to the encoder as NDN-TLV. This handles different
  630. * component types such as ImplicitSha256DigestComponent.
  631. * @param {Name.Component} component The name component to encode.
  632. * @param {TlvEncoder} encoder The encoder to receive the encoding.
  633. */
  634. Tlv0_2WireFormat.encodeNameComponent = function(component, encoder)
  635. {
  636. var type;
  637. if (component.getType() === ComponentType.OTHER_CODE)
  638. type = component.getOtherTypeCode();
  639. else
  640. // The enum values are the same as the TLV type codes.
  641. type = component.getType();
  642. encoder.writeBlobTlv(type, component.getValue().buf());
  643. };
  644. /**
  645. * Decode the name component as NDN-TLV and return the component. This handles
  646. * different component types such as ImplicitSha256DigestComponent.
  647. * @param {TlvDecoder} decoder The decoder with the input.
  648. * @param {boolean} copy (optional) If true, copy from the input when making new
  649. * Blob values. If false, then Blob values share memory with the input, which
  650. * must remain unchanged while the Blob values are used. If omitted, use true.
  651. * @return {Name.Component} A new Name.Component.
  652. */
  653. Tlv0_2WireFormat.decodeNameComponent = function(decoder, copy)
  654. {
  655. if (copy == null)
  656. copy = true;
  657. var savePosition = decoder.getOffset();
  658. var type = decoder.readVarNumber();
  659. // Restore the position.
  660. decoder.seek(savePosition);
  661. var value = new Blob(decoder.readBlobTlv(type), copy);
  662. if (type === Tlv.ImplicitSha256DigestComponent)
  663. return Name.Component.fromImplicitSha256Digest(value);
  664. else if (type === Tlv.NameComponent)
  665. return new Name.Component(value);
  666. else
  667. // Unrecognized type code.
  668. return new Name.Component(value, ComponentType.OTHER_CODE, type);
  669. };
  670. /**
  671. * Encode the name to the encoder.
  672. * @param {Name} name The name to encode.
  673. * @param {TlvEncoder} encoder The encoder to receive the encoding.
  674. * @return {object} An associative array with fields
  675. * (signedPortionBeginOffset, signedPortionEndOffset) where
  676. * signedPortionBeginOffset is the offset in the encoding of the beginning of
  677. * the signed portion, and signedPortionEndOffset is the offset in the encoding
  678. * of the end of the signed portion. The signed portion starts from the first
  679. * name component and ends just before the final name component (which is
  680. * assumed to be a signature for a signed interest).
  681. */
  682. Tlv0_2WireFormat.encodeName = function(name, encoder)
  683. {
  684. var saveLength = encoder.getLength();
  685. // Encode the components backwards.
  686. var signedPortionEndOffsetFromBack;
  687. for (var i = name.size() - 1; i >= 0; --i) {
  688. Tlv0_2WireFormat.encodeNameComponent(name.get(i), encoder);
  689. if (i == name.size() - 1)
  690. signedPortionEndOffsetFromBack = encoder.getLength();
  691. }
  692. var signedPortionBeginOffsetFromBack = encoder.getLength();
  693. encoder.writeTypeAndLength(Tlv.Name, encoder.getLength() - saveLength);
  694. var signedPortionBeginOffset =
  695. encoder.getLength() - signedPortionBeginOffsetFromBack;
  696. var signedPortionEndOffset;
  697. if (name.size() == 0)
  698. // There is no "final component", so set signedPortionEndOffset arbitrarily.
  699. signedPortionEndOffset = signedPortionBeginOffset;
  700. else
  701. signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
  702. return { signedPortionBeginOffset: signedPortionBeginOffset,
  703. signedPortionEndOffset: signedPortionEndOffset };
  704. };
  705. /**
  706. * Clear the name, decode a Name from the decoder and set the fields of the name
  707. * object.
  708. * @param {Name} name The name object whose fields are updated.
  709. * @param {TlvDecoder} decoder The decoder with the input.
  710. * @return {object} An associative array with fields
  711. * (signedPortionBeginOffset, signedPortionEndOffset) where
  712. * signedPortionBeginOffset is the offset in the encoding of the beginning of
  713. * the signed portion, and signedPortionEndOffset is the offset in the encoding
  714. * of the end of the signed portion. The signed portion starts from the first
  715. * name component and ends just before the final name component (which is
  716. * assumed to be a signature for a signed interest).
  717. */
  718. Tlv0_2WireFormat.decodeName = function(name, decoder, copy)
  719. {
  720. name.clear();
  721. var endOffset = decoder.readNestedTlvsStart(Tlv.Name);
  722. var signedPortionBeginOffset = decoder.getOffset();
  723. // In case there are no components, set signedPortionEndOffset arbitrarily.
  724. var signedPortionEndOffset = signedPortionBeginOffset;
  725. while (decoder.getOffset() < endOffset) {
  726. signedPortionEndOffset = decoder.getOffset();
  727. name.append(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
  728. }
  729. decoder.finishNestedTlvs(endOffset);
  730. return { signedPortionBeginOffset: signedPortionBeginOffset,
  731. signedPortionEndOffset: signedPortionEndOffset };
  732. };
  733. /**
  734. * Encode the interest selectors. If no selectors are written, do not output a
  735. * Selectors TLV.
  736. */
  737. Tlv0_2WireFormat.encodeSelectors = function(interest, encoder)
  738. {
  739. var saveLength = encoder.getLength();
  740. // Encode backwards.
  741. if (interest.getMustBeFresh())
  742. encoder.writeTypeAndLength(Tlv.MustBeFresh, 0);
  743. encoder.writeOptionalNonNegativeIntegerTlv(
  744. Tlv.ChildSelector, interest.getChildSelector());
  745. if (interest.getExclude().size() > 0)
  746. Tlv0_2WireFormat.encodeExclude(interest.getExclude(), encoder);
  747. if (interest.getKeyLocator().getType() != null)
  748. Tlv0_2WireFormat.encodeKeyLocator
  749. (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), encoder);
  750. encoder.writeOptionalNonNegativeIntegerTlv(
  751. Tlv.MaxSuffixComponents, interest.getMaxSuffixComponents());
  752. encoder.writeOptionalNonNegativeIntegerTlv(
  753. Tlv.MinSuffixComponents, interest.getMinSuffixComponents());
  754. // Only output the type and length if values were written.
  755. if (encoder.getLength() != saveLength)
  756. encoder.writeTypeAndLength(Tlv.Selectors, encoder.getLength() - saveLength);
  757. };
  758. Tlv0_2WireFormat.decodeSelectors = function(interest, decoder, copy)
  759. {
  760. if (copy == null)
  761. copy = true;
  762. var endOffset = decoder.readNestedTlvsStart(Tlv.Selectors);
  763. interest.setMinSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
  764. (Tlv.MinSuffixComponents, endOffset));
  765. interest.setMaxSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
  766. (Tlv.MaxSuffixComponents, endOffset));
  767. if (decoder.peekType(Tlv.PublisherPublicKeyLocator, endOffset))
  768. Tlv0_2WireFormat.decodeKeyLocator
  769. (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), decoder, copy);
  770. else
  771. interest.getKeyLocator().clear();
  772. if (decoder.peekType(Tlv.Exclude, endOffset))
  773. Tlv0_2WireFormat.decodeExclude(interest.getExclude(), decoder, copy);
  774. else
  775. interest.getExclude().clear();
  776. interest.setChildSelector(decoder.readOptionalNonNegativeIntegerTlv
  777. (Tlv.ChildSelector, endOffset));
  778. interest.setMustBeFresh(decoder.readBooleanTlv(Tlv.MustBeFresh, endOffset));
  779. decoder.finishNestedTlvs(endOffset);
  780. };
  781. Tlv0_2WireFormat.encodeExclude = function(exclude, encoder)
  782. {
  783. var saveLength = encoder.getLength();
  784. // TODO: Do we want to order the components (except for ANY)?
  785. // Encode the entries backwards.
  786. for (var i = exclude.size() - 1; i >= 0; --i) {
  787. var entry = exclude.get(i);
  788. if (entry == Exclude.ANY)
  789. encoder.writeTypeAndLength(Tlv.Any, 0);
  790. else
  791. Tlv0_2WireFormat.encodeNameComponent(entry, encoder);
  792. }
  793. encoder.writeTypeAndLength(Tlv.Exclude, encoder.getLength() - saveLength);
  794. };
  795. Tlv0_2WireFormat.decodeExclude = function(exclude, decoder, copy)
  796. {
  797. if (copy == null)
  798. copy = true;
  799. var endOffset = decoder.readNestedTlvsStart(Tlv.Exclude);
  800. exclude.clear();
  801. while (decoder.getOffset() < endOffset) {
  802. if (decoder.peekType(Tlv.Any, endOffset)) {
  803. // Read past the Any TLV.
  804. decoder.readBooleanTlv(Tlv.Any, endOffset);
  805. exclude.appendAny();
  806. }
  807. else
  808. exclude.appendComponent(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
  809. }
  810. decoder.finishNestedTlvs(endOffset);
  811. };
  812. Tlv0_2WireFormat.encodeKeyLocator = function(type, keyLocator, encoder)
  813. {
  814. var saveLength = encoder.getLength();
  815. // Encode backwards.
  816. if (keyLocator.getType() != null) {
  817. if (keyLocator.getType() == KeyLocatorType.KEYNAME)
  818. Tlv0_2WireFormat.encodeName(keyLocator.getKeyName(), encoder);
  819. else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
  820. keyLocator.getKeyData().size() > 0)
  821. encoder.writeBlobTlv(Tlv.KeyLocatorDigest, keyLocator.getKeyData().buf());
  822. else
  823. throw new Error("Unrecognized KeyLocatorType " + keyLocator.getType());
  824. }
  825. encoder.writeTypeAndLength(type, encoder.getLength() - saveLength);
  826. };
  827. Tlv0_2WireFormat.decodeKeyLocator = function
  828. (expectedType, keyLocator, decoder, copy)
  829. {
  830. if (copy == null)
  831. copy = true;
  832. var endOffset = decoder.readNestedTlvsStart(expectedType);
  833. keyLocator.clear();
  834. if (decoder.getOffset() == endOffset)
  835. // The KeyLocator is omitted, so leave the fields as none.
  836. return;
  837. if (decoder.peekType(Tlv.Name, endOffset)) {
  838. // KeyLocator is a Name.
  839. keyLocator.setType(KeyLocatorType.KEYNAME);
  840. Tlv0_2WireFormat.decodeName(keyLocator.getKeyName(), decoder, copy);
  841. }
  842. else if (decoder.peekType(Tlv.KeyLocatorDigest, endOffset)) {
  843. // KeyLocator is a KeyLocatorDigest.
  844. keyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST);
  845. keyLocator.setKeyData
  846. (new Blob(decoder.readBlobTlv(Tlv.KeyLocatorDigest), copy));
  847. }
  848. else
  849. throw new DecodingException(new Error
  850. ("decodeKeyLocator: Unrecognized key locator type"));
  851. decoder.finishNestedTlvs(endOffset);
  852. };
  853. Tlv0_2WireFormat.encodeValidityPeriod_ = function(validityPeriod, encoder)
  854. {
  855. var saveLength = encoder.getLength();
  856. // Encode backwards.
  857. encoder.writeBlobTlv(Tlv.ValidityPeriod_NotAfter,
  858. new Blob(Schedule.toIsoString(validityPeriod.getNotAfter())).buf());
  859. encoder.writeBlobTlv(Tlv.ValidityPeriod_NotBefore,
  860. new Blob(Schedule.toIsoString(validityPeriod.getNotBefore())).buf());
  861. encoder.writeTypeAndLength
  862. (Tlv.ValidityPeriod_ValidityPeriod, encoder.getLength() - saveLength);
  863. };
  864. Tlv0_2WireFormat.decodeValidityPeriod_ = function(validityPeriod, decoder)
  865. {
  866. var endOffset = decoder.readNestedTlvsStart(Tlv.ValidityPeriod_ValidityPeriod);
  867. validityPeriod.clear();
  868. // Set copy false since we just immediately get the string.
  869. var isoString = new Blob
  870. (decoder.readBlobTlv(Tlv.ValidityPeriod_NotBefore), false);
  871. var notBefore = Schedule.fromIsoString(isoString.toString());
  872. isoString = new Blob
  873. (decoder.readBlobTlv(Tlv.ValidityPeriod_NotAfter), false);
  874. var notAfter = Schedule.fromIsoString(isoString.toString());
  875. validityPeriod.setPeriod(notBefore, notAfter);
  876. decoder.finishNestedTlvs(endOffset);
  877. };
  878. /**
  879. * An internal method to encode signature as the appropriate form of
  880. * SignatureInfo in NDN-TLV.
  881. * @param {Signature} signature An object of a subclass of Signature to encode.
  882. * @param {TlvEncoder} encoder The encoder.
  883. */
  884. Tlv0_2WireFormat.encodeSignatureInfo_ = function(signature, encoder)
  885. {
  886. if (signature instanceof GenericSignature) {
  887. // Handle GenericSignature separately since it has the entire encoding.
  888. var encoding = signature.getSignatureInfoEncoding();
  889. // Do a test decoding to sanity check that it is valid TLV.
  890. try {
  891. var decoder = new TlvDecoder(encoding.buf());
  892. var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
  893. decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
  894. // Skip unrecognized TLVs, even if they have a critical type code.
  895. decoder.finishNestedTlvs(endOffset, true);
  896. } catch (ex) {
  897. throw new Error
  898. ("The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: " +
  899. ex.message);
  900. }
  901. encoder.writeBuffer(encoding.buf());
  902. return;
  903. }
  904. var saveLength = encoder.getLength();
  905. // Encode backwards.
  906. if (signature instanceof Sha256WithRsaSignature) {
  907. if (signature.getValidityPeriod().hasPeriod())
  908. Tlv0_2WireFormat.encodeValidityPeriod_
  909. (signature.getValidityPeriod(), encoder);
  910. Tlv0_2WireFormat.encodeKeyLocator
  911. (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
  912. encoder.writeNonNegativeIntegerTlv
  913. (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithRsa);
  914. }
  915. else if (signature instanceof Sha256WithEcdsaSignature) {
  916. if (signature.getValidityPeriod().hasPeriod())
  917. Tlv0_2WireFormat.encodeValidityPeriod_
  918. (signature.getValidityPeriod(), encoder);
  919. Tlv0_2WireFormat.encodeKeyLocator
  920. (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
  921. encoder.writeNonNegativeIntegerTlv
  922. (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithEcdsa);
  923. }
  924. else if (signature instanceof HmacWithSha256Signature) {
  925. Tlv0_2WireFormat.encodeKeyLocator
  926. (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
  927. encoder.writeNonNegativeIntegerTlv
  928. (Tlv.SignatureType, Tlv.SignatureType_SignatureHmacWithSha256);
  929. }
  930. else if (signature instanceof DigestSha256Signature)
  931. encoder.writeNonNegativeIntegerTlv
  932. (Tlv.SignatureType, Tlv.SignatureType_DigestSha256);
  933. else
  934. throw new Error("encodeSignatureInfo: Unrecognized Signature object type");
  935. encoder.writeTypeAndLength(Tlv.SignatureInfo, encoder.getLength() - saveLength);
  936. };
  937. Tlv0_2WireFormat.decodeSignatureInfo = function(data, decoder, copy)
  938. {
  939. if (copy == null)
  940. copy = true;
  941. var beginOffset = decoder.getOffset();
  942. var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
  943. var signatureType = decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
  944. if (signatureType == Tlv.SignatureType_SignatureSha256WithRsa) {
  945. data.setSignature(new Sha256WithRsaSignature());
  946. // Modify data's signature object because if we create an object
  947. // and set it, then data will have to copy all the fields.
  948. var signatureInfo = data.getSignature();
  949. Tlv0_2WireFormat.decodeKeyLocator
  950. (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
  951. if (decoder.peekType(Tlv.ValidityPeriod_ValidityPeriod, endOffset))
  952. Tlv0_2WireFormat.decodeValidityPeriod_
  953. (signatureInfo.getValidityPeriod(), decoder);
  954. }
  955. else if (signatureType == Tlv.SignatureType_SignatureSha256WithEcdsa) {
  956. data.setSignature(new Sha256WithEcdsaSignature());
  957. var signatureInfo = data.getSignature();
  958. Tlv0_2WireFormat.decodeKeyLocator
  959. (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
  960. if (decoder.peekType(Tlv.ValidityPeriod_ValidityPeriod, endOffset))
  961. Tlv0_2WireFormat.decodeValidityPeriod_
  962. (signatureInfo.getValidityPeriod(), decoder);
  963. }
  964. else if (signatureType == Tlv.SignatureType_SignatureHmacWithSha256) {
  965. data.setSignature(new HmacWithSha256Signature());
  966. var signatureInfo = data.getSignature();
  967. Tlv0_2WireFormat.decodeKeyLocator
  968. (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
  969. }
  970. else if (signatureType == Tlv.SignatureType_DigestSha256)
  971. data.setSignature(new DigestSha256Signature());
  972. else {
  973. data.setSignature(new GenericSignature());
  974. var signatureInfo = data.getSignature();
  975. // Get the bytes of the SignatureInfo TLV.
  976. signatureInfo.setSignatureInfoEncoding
  977. (new Blob(decoder.getSlice(beginOffset, endOffset), copy), signatureType);
  978. // Skip the remaining TLVs now, allowing unrecognized critical type codes.
  979. decoder.finishNestedTlvs(endOffset, true);
  980. }
  981. decoder.finishNestedTlvs(endOffset);
  982. };
  983. Tlv0_2WireFormat.encodeMetaInfo = function(metaInfo, encoder)
  984. {
  985. var saveLength = encoder.getLength();
  986. // Encode backwards.
  987. var finalBlockIdBuf = metaInfo.getFinalBlockId().getValue().buf();
  988. if (finalBlockIdBuf != null && finalBlockIdBuf.length > 0) {
  989. // FinalBlockId has an inner NameComponent.
  990. var finalBlockIdSaveLength = encoder.getLength();
  991. Tlv0_2WireFormat.encodeNameComponent(metaInfo.getFinalBlockId(), encoder);
  992. encoder.writeTypeAndLength
  993. (Tlv.FinalBlockId, encoder.getLength() - finalBlockIdSaveLength);
  994. }
  995. encoder.writeOptionalNonNegativeIntegerTlv
  996. (Tlv.FreshnessPeriod, metaInfo.getFreshnessPeriod());
  997. if (metaInfo.getType() != ContentType.BLOB) {
  998. // Not the default, so we need to encode the type.
  999. if (metaInfo.getType() == ContentType.LINK ||
  1000. metaInfo.getType() == ContentType.KEY ||
  1001. metaInfo.getType() == ContentType.NACK)
  1002. // The ContentType enum is set up with the correct integer for
  1003. // each NDN-TLV ContentType.
  1004. encoder.writeNonNegativeIntegerTlv(Tlv.ContentType, metaInfo.getType());
  1005. else if (metaInfo.getType() == ContentType.OTHER_CODE)
  1006. encoder.writeNonNegativeIntegerTlv
  1007. (Tlv.ContentType, metaInfo.getOtherTypeCode());
  1008. else
  1009. // We don't expect this to happen.
  1010. throw new Error("unrecognized TLV ContentType");
  1011. }
  1012. encoder.writeTypeAndLength(Tlv.MetaInfo, encoder.getLength() - saveLength);
  1013. };
  1014. Tlv0_2WireFormat.decodeMetaInfo = function(metaInfo, decoder, copy)
  1015. {
  1016. if (copy == null)
  1017. copy = true;
  1018. var endOffset = decoder.readNestedTlvsStart(Tlv.MetaInfo);
  1019. var type = decoder.readOptionalNonNegativeIntegerTlv
  1020. (Tlv.ContentType, endOffset);
  1021. if (type == null || type < 0 || type === ContentType.BLOB)
  1022. metaInfo.setType(ContentType.BLOB);
  1023. else if (type === ContentType.LINK ||
  1024. type === ContentType.KEY ||
  1025. type === ContentType.NACK)
  1026. // The ContentType enum is set up with the correct integer for each NDN-TLV
  1027. // ContentType.
  1028. metaInfo.setType(type);
  1029. else {
  1030. // Unrecognized content type.
  1031. metaInfo.setType(ContentType.OTHER_CODE);
  1032. metaInfo.setOtherTypeCode(type);
  1033. }
  1034. metaInfo.setFreshnessPeriod
  1035. (decoder.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod, endOffset));
  1036. if (decoder.peekType(Tlv.FinalBlockId, endOffset)) {
  1037. var finalBlockIdEndOffset = decoder.readNestedTlvsStart(Tlv.FinalBlockId);
  1038. metaInfo.setFinalBlockId(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
  1039. decoder.finishNestedTlvs(finalBlockIdEndOffset);
  1040. }
  1041. else
  1042. metaInfo.setFinalBlockId(null);
  1043. decoder.finishNestedTlvs(endOffset);
  1044. };
  1045. Tlv0_2WireFormat.encodeControlParameters = function(controlParameters, encoder)
  1046. {
  1047. var saveLength = encoder.getLength();
  1048. // Encode backwards.
  1049. encoder.writeOptionalNonNegativeIntegerTlv
  1050. (Tlv.ControlParameters_ExpirationPeriod,
  1051. controlParameters.getExpirationPeriod());
  1052. if (controlParameters.getStrategy().size() > 0){
  1053. var strategySaveLength = encoder.getLength();
  1054. Tlv0_2WireFormat.encodeName(controlParameters.getStrategy(), encoder);
  1055. encoder.writeTypeAndLength(Tlv.ControlParameters_Strategy,
  1056. encoder.getLength() - strategySaveLength);
  1057. }
  1058. var flags = controlParameters.getForwardingFlags().getNfdForwardingFlags();
  1059. if (flags != new ForwardingFlags().getNfdForwardingFlags())
  1060. // The flags are not the default value.
  1061. encoder.writeNonNegativeIntegerTlv
  1062. (Tlv.ControlParameters_Flags, flags);
  1063. encoder.writeOptionalNonNegativeIntegerTlv
  1064. (Tlv.ControlParameters_Cost, controlParameters.getCost());
  1065. encoder.writeOptionalNonNegativeIntegerTlv
  1066. (Tlv.ControlParameters_Origin, controlParameters.getOrigin());
  1067. encoder.writeOptionalNonNegativeIntegerTlv
  1068. (Tlv.ControlParameters_LocalControlFeature,
  1069. controlParameters.getLocalControlFeature());
  1070. if (controlParameters.getUri().length != 0)
  1071. encoder.writeBlobTlv
  1072. (Tlv.ControlParameters_Uri, new Blob(controlParameters.getUri()).buf());
  1073. encoder.writeOptionalNonNegativeIntegerTlv
  1074. (Tlv.ControlParameters_FaceId, controlParameters.getFaceId());
  1075. if (controlParameters.getName() != null)
  1076. Tlv0_2WireFormat.encodeName(controlParameters.getName(), encoder);
  1077. encoder.writeTypeAndLength
  1078. (Tlv.ControlParameters_ControlParameters, encoder.getLength() - saveLength);
  1079. };
  1080. Tlv0_2WireFormat.decodeControlParameters = function
  1081. (controlParameters, decoder, copy)
  1082. {
  1083. if (copy == null)
  1084. copy = true;
  1085. controlParameters.clear();
  1086. var endOffset = decoder.
  1087. readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);
  1088. // decode name
  1089. if (decoder.peekType(Tlv.Name, endOffset)) {
  1090. var name = new Name();
  1091. Tlv0_2WireFormat.decodeName(name, decoder, copy);
  1092. controlParameters.setName(name);
  1093. }
  1094. // decode face ID
  1095. controlParameters.setFaceId(decoder.readOptionalNonNegativeIntegerTlv
  1096. (Tlv.ControlParameters_FaceId, endOffset));
  1097. // decode URI
  1098. if (decoder.peekType(Tlv.ControlParameters_Uri, endOffset)) {
  1099. // Set copy false since we just immediately get the string.
  1100. var uri = new Blob
  1101. (decoder.readOptionalBlobTlv(Tlv.ControlParameters_Uri, endOffset), false);
  1102. controlParameters.setUri(uri.toString());
  1103. }
  1104. // decode integers
  1105. controlParameters.setLocalControlFeature(decoder.
  1106. readOptionalNonNegativeIntegerTlv(
  1107. Tlv.ControlParameters_LocalControlFeature, endOffset));
  1108. controlParameters.setOrigin(decoder.
  1109. readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,
  1110. endOffset));
  1111. controlParameters.setCost(decoder.readOptionalNonNegativeIntegerTlv(
  1112. Tlv.ControlParameters_Cost, endOffset));
  1113. // set forwarding flags
  1114. if (decoder.peekType(Tlv.ControlParameters_Flags, endOffset)) {
  1115. var flags = new ForwardingFlags();
  1116. flags.setNfdForwardingFlags(decoder.
  1117. readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags, endOffset));
  1118. controlParameters.setForwardingFlags(flags);
  1119. }
  1120. // decode strategy
  1121. if (decoder.peekType(Tlv.ControlParameters_Strategy, endOffset)) {
  1122. var strategyEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_Strategy);
  1123. Tlv0_2WireFormat.decodeName(controlParameters.getStrategy(), decoder, copy);
  1124. decoder.finishNestedTlvs(strategyEndOffset);
  1125. }
  1126. // decode expiration period
  1127. controlParameters.setExpirationPeriod(
  1128. decoder.readOptionalNonNegativeIntegerTlv(
  1129. Tlv.ControlParameters_ExpirationPeriod, endOffset));
  1130. decoder.finishNestedTlvs(endOffset);
  1131. };
  1132. /**
  1133. * Encode delegationSet to the encoder as a sequence of NDN-TLV Delegation.
  1134. * Note that the sequence of Delegation does not have an outer TLV type and
  1135. * length because (when used in a Link object) it is intended to use the type
  1136. * and length of a Data packet's Content.
  1137. * @param {DelegationSet} delegationSet The DelegationSet object to encode.
  1138. * @param {TlvEncoder} encoder The TlvEncoder to receive the encoding.
  1139. */
  1140. Tlv0_2WireFormat.encodeDelegationSet_ = function(delegationSet, encoder)
  1141. {
  1142. // Encode backwards.
  1143. for (var i = delegationSet.size() - 1; i >= 0; --i) {
  1144. var saveLength = encoder.getLength();
  1145. Tlv0_2WireFormat.encodeName(delegationSet.get(i).getName(), encoder);
  1146. encoder.writeNonNegativeIntegerTlv
  1147. (Tlv.Link_Preference, delegationSet.get(i).getPreference());
  1148. encoder.writeTypeAndLength
  1149. (Tlv.Link_Delegation, encoder.getLength() - saveLength);
  1150. }
  1151. };
  1152. /**
  1153. * Decode input as a sequence of NDN-TLV Delegation and set the fields of the
  1154. * delegationSet object. Note that the sequence of Delegation does not have an
  1155. * outer TLV type and length because (when used in a Link object) it is intended
  1156. * to use the type and length of a Data packet's Content.
  1157. * @param {DelegationSet} delegationSet The DelegationSet object whose fields
  1158. * are updated.
  1159. * @param {number} endOffset Decode elements up to endOffset in the input. This
  1160. * does not call finishNestedTlvs.
  1161. * @param {TlvDecoder} decoder The decoder with the input to decode.
  1162. * @param {boolean} copy If true, copy from the input when making new Blob
  1163. * values. If false, then Blob values share memory with the input, which must
  1164. * remain unchanged while the Blob values are used.
  1165. */
  1166. Tlv0_2WireFormat.decodeDelegationSet_ = function
  1167. (delegationSet, endOffset, decoder, copy)
  1168. {
  1169. delegationSet.clear();
  1170. while (decoder.getOffset() < endOffset) {
  1171. decoder.readTypeAndLength(Tlv.Link_Delegation);
  1172. var preference = decoder.readNonNegativeIntegerTlv(Tlv.Link_Preference);
  1173. var name = new Name();
  1174. Tlv0_2WireFormat.decodeName(name, decoder, copy);
  1175. // Add unsorted to preserve the order so that Interest selected delegation
  1176. // index will work.
  1177. delegationSet.addUnsorted(preference, name);
  1178. }
  1179. };
  1180. /**
  1181. * Decode input as an Interest in NDN-TLV format v0.3 and set the fields of
  1182. * the Interest object. This private method is called if the main decodeInterest
  1183. * fails to decode as v0.2. This ignores HopLimit and Parameters, and interprets
  1184. * CanBePrefix using MaxSuffixComponents.
  1185. * @param {Interest} interest The Interest object whose fields are updated.
  1186. * @param {Buffer} input The buffer with the bytes to decode.
  1187. * @param {boolean} copy (optional) If true, copy from the input when making new
  1188. * Blob values. If false, then Blob values share memory with the input, which
  1189. * must remain unchanged while the Blob values are used. If omitted, use true.
  1190. * @return {object} An associative array with fields
  1191. * (signedPortionBeginOffset, signedPortionEndOffset) where
  1192. * signedPortionBeginOffset is the offset in the encoding of the beginning of
  1193. * the signed portion, and signedPortionEndOffset is the offset in the encoding
  1194. * of the end of the signed portion. The signed portion starts from the first
  1195. * name component and ends just before the final name component (which is
  1196. * assumed to be a signature for a signed interest).
  1197. */
  1198. Tlv0_2WireFormat.decodeInterestV03_ = function(interest, input, copy)
  1199. {
  1200. if (copy == null)
  1201. copy = true;
  1202. var decoder = new TlvDecoder(input);
  1203. var endOffset = decoder.readNestedTlvsStart(Tlv.Interest);
  1204. var offsets = Tlv0_2WireFormat.decodeName(interest.getName(), decoder, copy);
  1205. // In v0.2 semantics, this calls setMaxSuffixComponents.
  1206. interest.setCanBePrefix(decoder.readBooleanTlv(Tlv.CanBePrefix, endOffset));
  1207. interest.setMustBeFresh(decoder.readBooleanTlv(Tlv.MustBeFresh, endOffset));
  1208. if (decoder.peekType(Tlv.ForwardingHint, endOffset)) {
  1209. var forwardingHintEndOffset = decoder.readNestedTlvsStart
  1210. (Tlv.ForwardingHint);
  1211. Tlv0_2WireFormat.decodeDelegationSet_
  1212. (interest.getForwardingHint(), forwardingHintEndOffset, decoder, copy);
  1213. decoder.finishNestedTlvs(forwardingHintEndOffset);
  1214. }
  1215. else
  1216. interest.getForwardingHint().clear();
  1217. var nonce = decoder.readOptionalBlobTlv(Tlv.Nonce, endOffset);
  1218. interest.setInterestLifetimeMilliseconds
  1219. (decoder.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime, endOffset));
  1220. // Clear the unused fields.
  1221. interest.setMinSuffixComponents(null);
  1222. interest.getKeyLocator().clear();
  1223. interest.getExclude().clear();
  1224. interest.setChildSelector(null);
  1225. interest.unsetLink();
  1226. interest.setSelectedDelegationIndex(null);
  1227. // Ignore the HopLimit and Parameters.
  1228. decoder.readOptionalBlobTlv(Tlv.HopLimit, endOffset);
  1229. decoder.readOptionalBlobTlv(Tlv.Parameters, endOffset);
  1230. // Set the nonce last because setting other interest fields clears it.
  1231. interest.setNonce(nonce == null ? new Blob() : new Blob(nonce, copy));
  1232. decoder.finishNestedTlvs(endOffset);
  1233. return offsets;
  1234. };