@masx200/zmodem.js
Version:
ZMODEM file transfers in JavaScript
138 lines (114 loc) • 3.76 kB
JavaScript
;
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;
}
},
};