slip.js 2.8 KB

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