Source: encoding/element-reader.js

  1. /**
  2. * Copyright (C) 2013-2016 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 DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
  21. var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
  22. var TlvStructureDecoder = require('./tlv/tlv-structure-decoder.js').TlvStructureDecoder; /** @ignore */
  23. var DecodingException = require('./decoding-exception.js').DecodingException; /** @ignore */
  24. var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
  25. var LOG = require('../log.js').Log.LOG;
  26. /**
  27. * A ElementReader lets you call onReceivedData multiple times which uses a
  28. * TlvStructureDecoder to detect the end of a TLV element and calls
  29. * elementListener.onReceivedElement(element) with the element. This handles
  30. * the case where a single call to onReceivedData may contain multiple elements.
  31. * @constructor
  32. * @param {{onReceivedElement:function}} elementListener
  33. */
  34. var ElementReader = function ElementReader(elementListener)
  35. {
  36. this.elementListener = elementListener;
  37. this.dataParts = [];
  38. this.tlvStructureDecoder = new TlvStructureDecoder();
  39. };
  40. exports.ElementReader = ElementReader;
  41. ElementReader.prototype.onReceivedData = function(/* Buffer */ data)
  42. {
  43. // Process multiple objects in the data.
  44. while (true) {
  45. var gotElementEnd;
  46. var offset;
  47. try {
  48. if (this.dataParts.length == 0) {
  49. // This is the beginning of an element.
  50. if (data.length <= 0)
  51. // Wait for more data.
  52. return;
  53. }
  54. // Scan the input to check if a whole TLV object has been read.
  55. this.tlvStructureDecoder.seek(0);
  56. gotElementEnd = this.tlvStructureDecoder.findElementEnd(data);
  57. offset = this.tlvStructureDecoder.getOffset();
  58. } catch (ex) {
  59. // Reset to read a new element on the next call.
  60. this.dataParts = [];
  61. this.tlvStructureDecoder = new TlvStructureDecoder();
  62. throw ex;
  63. }
  64. if (gotElementEnd) {
  65. // Got the remainder of an object. Report to the caller.
  66. this.dataParts.push(data.slice(0, offset));
  67. var element = DataUtils.concatArrays(this.dataParts);
  68. this.dataParts = [];
  69. // Reset to read a new object. Do this before calling onReceivedElement
  70. // in case it throws an exception.
  71. data = data.slice(offset, data.length);
  72. this.tlvStructureDecoder = new TlvStructureDecoder();
  73. this.elementListener.onReceivedElement(element);
  74. if (data.length == 0)
  75. // No more data in the packet.
  76. return;
  77. // else loop back to decode.
  78. }
  79. else {
  80. // Save a copy. We will call concatArrays later.
  81. var totalLength = data.length;
  82. for (var i = 0; i < this.dataParts.length; ++i)
  83. totalLength += this.dataParts[i].length;
  84. if (totalLength > NdnCommon.MAX_NDN_PACKET_SIZE) {
  85. // Reset to read a new element on the next call.
  86. this.dataParts = [];
  87. this.tlvStructureDecoder = new TlvStructureDecoder();
  88. throw new DecodingException(new Error
  89. ("The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()"));
  90. }
  91. this.dataParts.push(new Buffer(data));
  92. if (LOG > 3) console.log('Incomplete packet received. Length ' + data.length + '. Wait for more input.');
  93. return;
  94. }
  95. }
  96. };