slip.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. "use strict";
  2. const stream = require("stream");
  3. const Transform = stream.Transform;
  4. const Readable = stream.Readable;
  5. // https://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol
  6. const CODES = {
  7. frameEnd: 0xC0,
  8. frameEscape: 0xDB,
  9. transposedFrameEnd: 0xDC,
  10. transposedFrameEscape: 0xDD
  11. };
  12. let debug = () => {};
  13. class SlipDecoder extends Transform {
  14. constructor(options) {
  15. super(options);
  16. if (options.debug) {
  17. debug = options.debug;
  18. }
  19. this._slipping = false;
  20. this.resetDecoded();
  21. }
  22. resetDecoded() {
  23. this.decodedIndex = 0;
  24. this.decoded = new Buffer(256);
  25. }
  26. // TODO:csd - Write flush
  27. _transform(chunk, encoding, done) {
  28. debug("SlipDecoder._transform", encoding, chunk.length);
  29. for (let index = 0; index < chunk.length; index++) {
  30. let val = chunk[index];
  31. if (val === CODES.frameEnd) {
  32. debug("frameEnd detected");
  33. if (this._slipping) {
  34. this._slipping = false;
  35. // Return all of decoded
  36. this.push(this.decoded.slice(0, this.decodedIndex));
  37. debug("Resetting buffer");
  38. this.resetDecoded();
  39. } else {
  40. this._slipping = true;
  41. }
  42. continue;
  43. }
  44. if (this._slipping) {
  45. // Slip decoding
  46. if (val === CODES.frameEscape) {
  47. // Move one past the escape char
  48. index++;
  49. if (chunk[index] === CODES.transposedFrameEnd) {
  50. val = CODES.frameEnd;
  51. } else if (chunk[index] === CODES.transposedFrameEscape) {
  52. val = CODES.frameEscape;
  53. }
  54. }
  55. this.decoded[this.decodedIndex++] = val;
  56. }
  57. }
  58. done();
  59. }
  60. }
  61. class SlipEncoder extends Transform {
  62. _transform(chunk, encoding, done) {
  63. debug("SlipEncoder._transform", encoding);
  64. let encoded = new Buffer(chunk.length + 100);
  65. let encodedIndex = 0;
  66. encoded[encodedIndex++] = CODES.frameEnd;
  67. for (var i = 0; i < chunk.length; i++) {
  68. if (chunk[i] === CODES.frameEnd) {
  69. encoded[encodedIndex++] = CODES.frameEscape;
  70. encoded[encodedIndex++] = CODES.transposedFrameEnd;
  71. } else if (chunk[i] === CODES.frameEscape) {
  72. encoded[encodedIndex++] = CODES.frameEscape;
  73. encoded[encodedIndex++] = CODES.transposedFrameEscape;
  74. } else {
  75. encoded[encodedIndex++] = chunk[i];
  76. }
  77. }
  78. encoded[encodedIndex++] = CODES.frameEnd;
  79. this.push(encoded.slice(0, encodedIndex), encoding);
  80. done();
  81. }
  82. }
  83. module.exports = {
  84. SlipDecoder: SlipDecoder,
  85. SlipEncoder: SlipEncoder
  86. }