@octalmage/node-appletv
Version:
A Node.js library for communicating with an Apple TV
95 lines (94 loc) • 3.23 kB
JavaScript
;
/**
* Type Length Value encoding/decoding, used by HAP as a wire format.
* https://en.wikipedia.org/wiki/Type-length-value
*
* Originally based on code from github:KhaosT/HAP-NodeJS@0c8fd88 used
* used per the terms of the Apache Software License v2.
*
* Original code copyright Khaos Tian <khaos.tian@gmail.com>
*
* Modifications copyright Zach Bean <zb@forty2.com>
* * Reformatted for ES6-style module
* * Rewrote encode() to be non-recursive; also simplified the logic
* * Rewrote decode()
*/
Object.defineProperty(exports, "__esModule", { value: true });
const Tag = {
PairingMethod: 0x00,
Username: 0x01,
Salt: 0x02,
// could be either the SRP client public key (384 bytes) or the ED25519 public key (32 bytes), depending on context
PublicKey: 0x03,
Proof: 0x04,
EncryptedData: 0x05,
Sequence: 0x06,
ErrorCode: 0x07,
BackOff: 0x08,
Signature: 0x0A,
MFiCertificate: 0x09,
MFiSignature: 0x0A
};
function encode(type, data, ...args) {
var encodedTLVBuffer = Buffer.alloc(0);
// coerce data to Buffer if needed
if (typeof data === 'number')
data = Buffer.from([data]);
else if (typeof data === 'string')
data = Buffer.from(data);
if (data.length <= 255) {
encodedTLVBuffer = Buffer.concat([Buffer.from([type, data.length]), data]);
}
else {
var leftLength = data.length;
var tempBuffer = Buffer.alloc(0);
var currentStart = 0;
for (; leftLength > 0;) {
if (leftLength >= 255) {
tempBuffer = Buffer.concat([tempBuffer, Buffer.from([type, 0xFF]), data.slice(currentStart, currentStart + 255)]);
leftLength -= 255;
currentStart = currentStart + 255;
}
else {
tempBuffer = Buffer.concat([tempBuffer, Buffer.from([type, leftLength]), data.slice(currentStart, currentStart + leftLength)]);
leftLength -= leftLength;
}
}
encodedTLVBuffer = tempBuffer;
}
// do we have more to encode?
if (arguments.length > 2) {
// chop off the first two arguments which we already processed, and process the rest recursively
var remainingArguments = Array.prototype.slice.call(arguments, 2);
var remainingTLVBuffer = encode.apply(this, remainingArguments);
// append the remaining encoded arguments directly to the buffer
encodedTLVBuffer = Buffer.concat([encodedTLVBuffer, remainingTLVBuffer]);
}
return encodedTLVBuffer;
}
function decode(data) {
var objects = {};
var leftLength = data.length;
var currentIndex = 0;
for (; leftLength > 0;) {
var type = data[currentIndex];
var length = data[currentIndex + 1];
currentIndex += 2;
leftLength -= 2;
var newData = data.slice(currentIndex, currentIndex + length);
if (objects[type]) {
objects[type] = Buffer.concat([objects[type], newData]);
}
else {
objects[type] = newData;
}
currentIndex += length;
leftLength -= length;
}
return objects;
}
exports.default = {
Tag,
encode,
decode
};