parser.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. var util = require('util');
  2. var events = require('events');
  3. var StompFrame = require('./frame').StompFrame;
  4. var ParserStates = {
  5. COMMAND: 0,
  6. HEADERS: 1,
  7. BODY: 2,
  8. ERROR: 3
  9. };
  10. function StompFrameEmitter(frameValidators) {
  11. events.EventEmitter.call(this);
  12. this.state = ParserStates.COMMAND;
  13. this.frame = new StompFrame();
  14. this.frames = [];
  15. this.buffer = '';
  16. this.frameValidators = frameValidators || {};
  17. this.commands = Object.keys(this.frameValidators);
  18. }
  19. util.inherits(StompFrameEmitter, events.EventEmitter);
  20. StompFrameEmitter.prototype.incrementState = function () {
  21. if (this.state === ParserStates.BODY || this.state === ParserStates.ERROR) {
  22. this.state = ParserStates.COMMAND;
  23. } else {
  24. this.state++;
  25. }
  26. };
  27. StompFrameEmitter.prototype.handleData = function (data) {
  28. this.buffer += data;
  29. do {
  30. if (this.state === ParserStates.COMMAND) {
  31. this.parseCommand();
  32. }
  33. if (this.state === ParserStates.HEADERS) {
  34. this.parseHeaders();
  35. }
  36. if (this.state === ParserStates.BODY) {
  37. this.parseBody();
  38. }
  39. if (this.state === ParserStates.ERROR) {
  40. this.parseError();
  41. }
  42. } while (this.state === ParserStates.COMMAND && this.hasLine());
  43. };
  44. StompFrameEmitter.prototype.hasLine = function () {
  45. return (this.buffer.indexOf('\n') > -1);
  46. };
  47. StompFrameEmitter.prototype.popLine = function () {
  48. var index = this.buffer.indexOf('\n');
  49. var line = this.buffer.slice(0, index);
  50. this.buffer = this.buffer.substr(index + 1);
  51. return line;
  52. };
  53. StompFrameEmitter.prototype.error = function (err) {
  54. this.emit('parseError', err);
  55. this.state = ParserStates.ERROR;
  56. };
  57. StompFrameEmitter.prototype.parseCommand = function () {
  58. while (this.hasLine()) {
  59. var line = this.popLine();
  60. if (line !== '') {
  61. if (this.commands.indexOf(line) === -1) {
  62. this.error({
  63. message: 'No such command ',
  64. details: 'Unrecognized Command \'' + line + '\''
  65. });
  66. break;
  67. }
  68. this.frame.setCommand(line);
  69. this.incrementState();
  70. break;
  71. }
  72. }
  73. };
  74. StompFrameEmitter.prototype.parseHeaders = function () {
  75. while (this.hasLine()) {
  76. var line = this.popLine();
  77. if (line === '') {
  78. this.incrementState();
  79. break;
  80. } else {
  81. var kv = line.split(':');
  82. if (kv.length < 2) {
  83. this.error({
  84. message: 'Error parsing header',
  85. details: 'No ":" in line "' + line + '"'
  86. });
  87. break;
  88. }
  89. this.frame.setHeader(kv[0], kv.slice(1).join(':'));
  90. }
  91. }
  92. };
  93. StompFrameEmitter.prototype.parseBody = function () {
  94. var bufferBuffer = new Buffer(this.buffer);
  95. if (this.frame.contentLength > -1) {
  96. var remainingLength = this.frame.contentLength - this.frame.body.length;
  97. if(remainingLength < bufferBuffer.length) {
  98. this.frame.appendToBody(bufferBuffer.slice(0, remainingLength).toString());
  99. this.buffer = bufferBuffer.slice(remainingLength, bufferBuffer.length).toString();
  100. if (this.frame.contentLength === Buffer.byteLength(this.frame.body)) {
  101. this.frame.contentLength = -1;
  102. } else {
  103. return;
  104. }
  105. }
  106. }
  107. var index = this.buffer.indexOf('\0');
  108. if (index == -1) {
  109. this.frame.appendToBody(this.buffer);
  110. this.buffer = '';
  111. } else {
  112. // The end of the frame has been identified, finish creating it
  113. this.frame.appendToBody(this.buffer.slice(0, index));
  114. var frameValidation = this.getFrameValidation(this.frame.command);
  115. if (frameValidation.isValid) {
  116. // Emit the frame and reset
  117. this.emit('frame', this.frame); // Event emit to catch any frame emission
  118. this.emit(this.frame.command, this.frame); // Specific frame emission
  119. } else {
  120. this.emit('parseError', {
  121. message: frameValidation.message,
  122. details: frameValidation.details,
  123. });
  124. }
  125. this.frame = new StompFrame();
  126. this.incrementState();
  127. this.buffer = this.buffer.substr(index + 1);
  128. }
  129. };
  130. StompFrameEmitter.prototype.getFrameValidation = function (command) {
  131. if (!this.frameValidators.hasOwnProperty(command)) {
  132. this.emit('parseError', { message: 'No validator defined for ' + command });
  133. } else {
  134. return this.frame.validate(this.frameValidators[command]);
  135. }
  136. };
  137. StompFrameEmitter.prototype.parseError = function () {
  138. var index = this.buffer.indexOf('\0');
  139. if (index > -1) {
  140. this.buffer = this.buffer.substr(index + 1);
  141. this.incrementState();
  142. } else {
  143. this.buffer = "";
  144. }
  145. };
  146. new StompFrameEmitter();
  147. exports.StompFrameEmitter = StompFrameEmitter;