packet_parser.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. var Packet = require('./packets/packet.js');
  2. function PacketParser(onPacket)
  3. {
  4. // array of last payload chunks
  5. // only used when corrent payload is not complete
  6. this.buffer = [];
  7. // total length of chunks on buffer
  8. this.bufferLength = 0;
  9. // incomplete header state: number of header bytes received
  10. this.headerLen = 0;
  11. // expected payload length
  12. this.length = 0;
  13. this.onPacket = onPacket;
  14. this.execute = PacketParser.prototype.executeStart;
  15. }
  16. function readPacketLength(b,off) {
  17. var b0 = b[off];
  18. var b1 = b[off+1];
  19. var b2 = b[off+2];
  20. if (b1 + b2 === 0)
  21. return b0;
  22. return b0 + (b1<<8) + (b2<<16);
  23. }
  24. //
  25. PacketParser.prototype.executeStart = function executeStart(chunk) {
  26. var start = 0;
  27. var end = chunk.length;
  28. // if (start-end === 0) return;
  29. while (end - start >= 3) {
  30. this.length = readPacketLength(chunk, start);
  31. if (end - start >= this.length + 4) { // at least one more full packet
  32. this.onPacket(new Packet(chunk[start+3], chunk, start + 4, start + 4 + this.length));
  33. start += 4 + this.length;
  34. } else { // payload is incomplete
  35. this.buffer = [chunk.slice(start + 3, end)];
  36. this.bufferLength = end - start - 3;
  37. this.execute = PacketParser.prototype.executePayload;
  38. return;
  39. }
  40. }
  41. if (end - start > 0) { // there is start of length header, but it's not full 3 bytes
  42. this.headerLen = end - start; // 1 or 2 bytes
  43. this.length = chunk[start];
  44. if (this.headerLen == 2) {
  45. this.length = chunk[start] + (chunk[start+1] << 8);
  46. this.execute = PacketParser.prototype.executeHeader3;
  47. } else {
  48. this.execute = PacketParser.prototype.executeHeader2;
  49. }
  50. }
  51. }
  52. PacketParser.prototype.executePayload = function executePayload(chunk) {
  53. var start = 0;
  54. var end = chunk.length;
  55. var remainingPayload = this.length - this.bufferLength + 1;
  56. if (end - start >= remainingPayload) { // last chunk for payload
  57. var payload = new Buffer(this.length + 1);
  58. var offset = 0;
  59. for (var i=0; i < this.buffer.length; ++i) {
  60. this.buffer[i].copy(payload, offset);
  61. offset += this.buffer[i].length;
  62. }
  63. chunk.copy(payload, offset, start, start + remainingPayload);
  64. this.onPacket(new Packet(payload[0], payload, 1, this.length + 1));
  65. this.buffer = [];
  66. this.bufferLength = 0;
  67. this.execute = PacketParser.prototype.executeStart;
  68. start += remainingPayload;
  69. if (end - start > 0)
  70. return this.execute(chunk.slice(start, end));
  71. } else {
  72. this.buffer.push(chunk);
  73. this.bufferLength += chunk.length;
  74. }
  75. }
  76. PacketParser.prototype.executeHeader2 = function executeHeader2(chunk) {
  77. this.length += chunk[0] << 8;
  78. if (chunk.length > 1) {
  79. this.length += chunk[1] << 16;
  80. this.execute = PacketParser.prototype.executePayload;
  81. return this.executePayload(chunk.slice(2));
  82. } else {
  83. this.execute = PacketParser.prototype.executeHeader3;
  84. }
  85. }
  86. PacketParser.prototype.executeHeader3 = function executeHeader3(chunk) {
  87. this.length += chunk[0] << 16;
  88. this.execute = PacketParser.prototype.executePayload;
  89. return this.executePayload(chunk.slice(1));
  90. }
  91. module.exports = PacketParser;