react-native-androidtv-remote
Version:
Port of AndroidTV Remote to react native
178 lines (169 loc) • 7.57 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PairingManager = void 0;
require("core-js/modules/es.error.cause.js");
require("core-js/modules/es.json.stringify.js");
require("core-js/modules/es.parse-int.js");
require("core-js/modules/es.promise.js");
var _PairingMessageManager = require("./PairingMessageManager.js");
var _nodeForge = _interopRequireDefault(require("node-forge"));
var _buffer = require("buffer");
var _events = _interopRequireDefault(require("events"));
var _reactNativeTcpSocket = _interopRequireDefault(require("react-native-tcp-socket"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
//import RNFS from 'react-native-fs';
class PairingManager extends _events.default {
constructor(host, port, certs, service_name, systeminfo) {
super();
this.host = host;
this.port = port;
this.chunks = _buffer.Buffer.from([]);
this.certs = certs;
this.service_name = service_name;
this.pairingMessageManager = new _PairingMessageManager.PairingMessageManager(systeminfo);
this.isCancelled = false;
}
/*
async logCertificates(clientCert, serverCert) {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const logDir = `${RNFS.DocumentDirectoryPath}/logs`;
const logFile = `${logDir}/certificates-${timestamp}.log`;
try {
// Create logs directory if it doesn't exist
await RNFS.mkdir(logDir, { NSURLIsExcludedFromBackupKey: true });
const logContent = `
=== Certificate Log Generated at ${new Date().toISOString()} ===
Client Certificate:
${JSON.stringify(clientCert, null, 2)}
Server Certificate:
${JSON.stringify(serverCert, null, 2)}
`;
await RNFS.writeFile(logFile, logContent, 'utf8');
console.debug(`Certificates logged to: ${logFile}`);
// Log the full path for debugging
console.debug('Document Directory:', RNFS.DocumentDirectoryPath);
} catch (error) {
console.error('Error writing certificate logs:', error);
}
}*/
sendCode(code) {
var _this = this;
return _asyncToGenerator(function* () {
console.debug("Sending code : ", code);
var code_bytes = _this.hexStringToBytes(code);
var client_certificate = yield _this.client.getCertificate();
var server_certificate = yield _this.client.getPeerCertificate();
//await this.logCertificates(client_certificate, server_certificate);
var sha256 = _nodeForge.default.md.sha256.create();
sha256.update(_nodeForge.default.util.hexToBytes(client_certificate.modulus), 'raw');
sha256.update(_nodeForge.default.util.hexToBytes("0" + client_certificate.exponent.slice(2)), 'raw');
sha256.update(_nodeForge.default.util.hexToBytes(server_certificate.modulus), 'raw');
sha256.update(_nodeForge.default.util.hexToBytes("0" + server_certificate.exponent.slice(2)), 'raw');
sha256.update(_nodeForge.default.util.hexToBytes(code.slice(2)), 'raw');
var hash = sha256.digest().getBytes();
var hash_array = Array.from(hash, c => c.charCodeAt(0) & 0xff);
var check = hash_array[0];
if (check !== code_bytes[0]) {
console.error("Code validation failed");
_this.client.destroy(new Error("Bad Code"));
return false;
} else {
console.debug("Code validated, sending pairing secret");
_this.client.write(_this.pairingMessageManager.createPairingSecret(hash_array));
return true;
}
})();
}
cancelPairing() {
this.isCancelled = true;
this.client.destroy(new Error("Pairing canceled"));
return false;
}
start() {
var _this2 = this;
return _asyncToGenerator(function* () {
return new Promise((resolve, reject) => {
var options = {
port: _this2.port,
host: _this2.host,
key: _this2.certs.key,
cert: _this2.certs.cert,
rejectUnauthorized: false,
// if true => use ca
// Specific to react-native-tcp-socket (patched)
androidKeyStore: _this2.certs.androidKeyStore,
certAlias: _this2.certs.certAlias,
keyAlias: _this2.certs.keyAlias
};
//console.debug('PairingManager.start(): before connectTLS');
_this2.client = _reactNativeTcpSocket.default.connectTLS(options, () => {
console.debug(_this2.host + " Pairing connected");
});
_this2.isCancelled = false;
_this2.client.pairingManager = _this2;
_this2.client.on("secureConnect", () => {
console.debug(_this2.host + " Pairing secure connected ");
_this2.client.write(_this2.pairingMessageManager.createPairingRequest(_this2.service_name));
});
_this2.client.on('data', data => {
var buffer = _buffer.Buffer.from(data);
_this2.chunks = _buffer.Buffer.concat([_this2.chunks, buffer]);
if (_this2.chunks.length > 0 && _this2.chunks.readInt8(0) === _this2.chunks.length - 1) {
var message = _this2.pairingMessageManager.parse(_this2.chunks);
console.debug("Receive : " + Array.from(_this2.chunks));
console.debug("Receive : " + JSON.stringify(message.toJSON()));
if (message.status !== _this2.pairingMessageManager.Status.STATUS_OK) {
_this2.client.destroy(new Error(message.status));
} else {
if (message.pairingRequestAck) {
_this2.client.write(_this2.pairingMessageManager.createPairingOption());
} else if (message.pairingOption) {
_this2.client.write(_this2.pairingMessageManager.createPairingConfiguration());
} else if (message.pairingConfigurationAck) {
_this2.emit('secret');
} else if (message.pairingSecretAck) {
console.debug(_this2.host + " Paired!");
_this2.client.destroy();
} else {
console.debug(_this2.host + " What Else ?");
}
}
_this2.chunks = _buffer.Buffer.from([]);
}
});
_this2.client.on('close', hasError => {
if (hasError) {
console.log('PairingManager.close() failure');
reject(false);
} else if (_this2.isCancelled) {
console.log('PairingManager.close() on cancelPairing()');
_this2.isCancelled = false;
reject(false);
} else {
console.log('PairingManager.close() success');
resolve(true);
}
});
_this2.client.on('error', error => {
console.error(error);
});
});
})();
}
hexStringToBytes(q) {
var bytes = [];
for (var i = 0; i < q.length; i += 2) {
var byte = parseInt(q.substring(i, i + 2), 16);
if (byte > 127) {
byte = -(~byte & 0xFF) - 1;
}
bytes.push(byte);
}
return bytes;
}
}
exports.PairingManager = PairingManager;