UNPKG

@octalmage/node-appletv

Version:

A Node.js library for communicating with an Apple TV

95 lines (94 loc) 3.23 kB
"use strict"; /** * 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 };