summaryrefslogtreecommitdiffstats
path: root/src/zcrc.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/zcrc.js')
-rw-r--r--src/zcrc.js143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/zcrc.js b/src/zcrc.js
new file mode 100644
index 0000000..831f835
--- /dev/null
+++ b/src/zcrc.js
@@ -0,0 +1,143 @@
+"use strict";
+
+const CRC32_MOD = require('crc-32');
+
+var Zmodem = module.exports;
+
+Object.assign(
+ Zmodem,
+ require("./zerror"),
+ require("./encode")
+);
+
+//----------------------------------------------------------------------
+// BEGIN adapted from crc-js by Johannes Rudolph
+
+var _crctab;
+
+const
+ crc_width = 16,
+ crc_polynomial = 0x1021,
+ crc_castmask = 0xffff,
+ crc_msbmask = 1 << (crc_width - 1)
+;
+
+function _compute_crctab() {
+ _crctab = new Array(256);
+
+ var divident_shift = crc_width - 8;
+
+ for (var divident = 0; divident < 256; divident++) {
+ var currByte = (divident << divident_shift) & crc_castmask;
+
+ for (var bit = 0; bit < 8; bit++) {
+
+ if ((currByte & crc_msbmask) !== 0) {
+ currByte <<= 1;
+ currByte ^= crc_polynomial;
+ }
+ else {
+ currByte <<= 1;
+ }
+ }
+
+ _crctab[divident] = (currByte & crc_castmask);
+ }
+}
+
+// END adapted from crc-js by Johannes Rudolph
+//----------------------------------------------------------------------
+
+function _updcrc(cp, crc) {
+ if (!_crctab) _compute_crctab();
+
+ return(
+ _crctab[((crc >> 8) & 255)]
+ ^ ((255 & crc) << 8)
+ ^ cp
+ );
+}
+
+function __verify(expect, got) {
+ var err;
+
+ if ( expect.join() !== got.join() ) {
+ throw new Zmodem.Error("crc", got, expect);
+ }
+}
+
+//TODO: use external implementation(s)
+Zmodem.CRC = {
+
+ //https://www.lammertbies.nl/comm/info/crc-calculation.html
+ //CRC-CCITT (XModem)
+
+ /**
+ * Deduce a given set of octet values’ CRC16, as per the CRC16
+ * variant that ZMODEM uses (CRC-CCITT/XModem).
+ *
+ * @param {Array} octets - The array of octet values.
+ * Each array member should be an 8-bit unsigned integer (0-255).
+ *
+ * @returns {Array} crc - The CRC, expressed as an array of octet values.
+ */
+ crc16: function crc16(octet_nums) {
+ var crc = octet_nums[0];
+ for (var b=1; b<octet_nums.length; b++) {
+ crc = _updcrc( octet_nums[b], crc );
+ }
+
+ crc = _updcrc( 0, _updcrc(0, crc) );
+
+ //a big-endian 2-byte sequence
+ return Zmodem.ENCODELIB.pack_u16_be(crc);
+ },
+
+ /**
+ * Deduce a given set of octet values’ CRC32.
+ *
+ * @param {Array} octets - The array of octet values.
+ * Each array member should be an 8-bit unsigned integer (0-255).
+ *
+ * @returns {Array} crc - The CRC, expressed as an array of octet values.
+ */
+ crc32: function crc32(octet_nums) {
+ return Zmodem.ENCODELIB.pack_u32_le(
+ CRC32_MOD.buf(octet_nums) >>> 0 //bit-shift to get unsigned
+ );
+ },
+
+ /**
+ * Verify a given set of octet values’ CRC16.
+ * An exception is thrown on failure.
+ *
+ * @param {Array} bytes_arr - The array of octet values.
+ * Each array member should be an 8-bit unsigned integer (0-255).
+ *
+ * @param {Array} crc - The CRC to check against, expressed as
+ * an array of octet values.
+ */
+ verify16: function verify16(bytes_arr, got) {
+ return __verify( this.crc16(bytes_arr), got );
+ },
+
+ /**
+ * Verify a given set of octet values’ CRC32.
+ * An exception is thrown on failure.
+ *
+ * @param {Array} bytes_arr - The array of octet values.
+ * Each array member should be an 8-bit unsigned integer (0-255).
+ *
+ * @param {Array} crc - The CRC to check against, expressed as
+ * an array of octet values.
+ */
+ verify32: function verify32(bytes_arr, crc) {
+ try {
+ __verify( this.crc32(bytes_arr), crc );
+ }
+ catch(err) {
+ err.input = bytes_arr.slice(0);
+ throw err;
+ }
+ },
+};