144 lines
3.7 KiB
JavaScript
144 lines
3.7 KiB
JavaScript
|
"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;
|
|||
|
}
|
|||
|
},
|
|||
|
};
|