added TLS support

This commit is contained in:
Overtorment
2020-03-26 15:04:02 +00:00
parent 609ca3bd58
commit aa73cd8bb3
5 changed files with 144 additions and 11 deletions

View File

@@ -67,8 +67,16 @@ class ElectrumClient extends Client {
}, 10000);
}
close() {
super.close();
if (this.timeout != null) {
clearTimeout(this.timeout);
}
this.reconnect = this.onClose = this.keepAlive = () => {}; // dirty hack to make it stop reconnecting
}
reconnect() {
this.initSocketConnection();
this.initSocket();
return this.initElectrum(this.electrumConfig);
}

View File

@@ -1,3 +0,0 @@
class TlsSocket {
constructor() {}
}

126
lib/TlsSocketWrapper.js Normal file
View File

@@ -0,0 +1,126 @@
/**
* Simple wrapper to mimick Socket class from NET package, since TLS package havs slightly different API.
* We implement several methods that TCP sockets are expected to have. We will proxy call them as soon as
* realt TLS socket will be created (TLS socket created after connection).
*/
class TlsSocketWrapper {
constructor(tls) {
this._tls = tls; // dependency injection lol
this._socket = false;
// defaults:
this._timeout = 10000;
this._encoding = 'utf8';
this._keepAliveEneblad = true;
this._keepAliveinitialDelay = 0;
this._noDelay = true;
this._listeners = {};
}
setTimeout(timeout) {
this._timeout = timeout;
}
setEncoding(encoding) {
this._encoding = encoding;
}
setKeepAlive(enabled, initialDelay) {
this._keepAliveEneblad = enabled;
this._keepAliveinitialDelay = initialDelay;
}
setNoDelay(noDelay) {
this._noDelay = noDelay;
}
on(event, listener) {
this._listeners[event] = this._listeners[event] || [];
this._listeners[event].push(listener);
}
removeListener(event, listener) {
this._listeners[event] = this._listeners[event] || [];
let newListeners = [];
let found = false;
for (let savedListener of this._listeners[event]) {
if (savedListener == listener) {
// found our listener
found = true;
// we just skip it
} else {
// other listeners should go back to original array
newListeners.push(savedListener);
}
}
if (found) {
this._listeners[event] = newListeners;
} else {
// something went wrong, lets just cleanup all listeners
this._listeners[event] = [];
}
}
connect(port, host, callback) {
// resulting TLSSocket extends <net.Socket>
this._socket = tls.connect({ port: port, host: host, rejectUnauthorized: false }, () => {
// socket.write('{ "id": 5, "method": "blockchain.estimatefee", "params": [2] }\n')
console.log('TLS Connected to ', host, port);
return callback();
});
// setting everything that was set to this proxy class
this._socket.setTimeout(this._timeout);
this._socket.setEncoding(this._encoding);
this._socket.setKeepAlive(this._keepAliveEneblad, this._keepAliveinitialDelay);
this._socket.setNoDelay(this._noDelay);
// resubscribing to events on newly created socket so we could proxy them to already established listeners
this._socket.on('data', data => {
this._passOnEvent('data', data);
});
this._socket.on('end', data => {
this._passOnEvent('end', data);
});
this._socket.on('timeout', () => {
this._passOnEvent('timeout');
});
this._socket.on('error', data => {
this._passOnEvent('error', data);
});
this._socket.on('close', data => {
this._passOnEvent('close', data);
});
this._socket.on('connect', data => {
this._passOnEvent('connect', data);
});
}
_passOnEvent(event, data) {
this._listeners[event] = this._listeners[event] || [];
for (let savedListener of this._listeners[event]) {
savedListener(data);
}
}
emit(event, data) {
this._socket.emit(event, data);
}
end() {
this._socket.end();
}
destroy() {
this._socket.destroy();
}
write(data) {
this._socket.write(data);
}
}
module.exports = TlsSocketWrapper;

View File

@@ -1,17 +1,19 @@
'use strict';
/**
* expecting NET to be injected from outside:
* expecting NET & TLS to be injected from outside:
* for RN it should be in shim.js:
* global.net = require('react-native-tcp');
* global.tls = require('react-native-tcp/tls');
*
* for nodejs tests it should be provided before tests:
* global.net = require('net');
* global.tls = require('tls');
* */
let net = global.net;
let tls = global.tls;
const TIMEOUT = 10000;
const TlsSocket = require('./TlsSocket.js');
const TlsSocketWrapper = require('./TlsSocketWrapper.js');
const EventEmitter = require('events').EventEmitter;
const util = require('./util');
@@ -25,10 +27,10 @@ class Client {
this.mp = new util.MessageParser((body, n) => {
this.onMessage(body, n);
});
this.initSocketConnection(protocol, options);
this.initSocket(protocol, options);
}
initSocketConnection(protocol, options) {
initSocket(protocol, options) {
switch (protocol) {
case 'tcp':
this.conn = new net.Socket();
@@ -38,7 +40,7 @@ class Client {
if (!tls) {
throw new Error('tls package could not be loaded');
}
this.conn = {}; // TODO
this.conn = new TlsSocketWrapper(tls);
break;
default:
throw new Error('unknown protocol');

View File

@@ -1,6 +1,6 @@
{
"name": "electrum-client",
"version": "1.0.0",
"version": "1.1.0",
"description": "Electrum protocol client for React Native & Node.js",
"main": "index.js",
"scripts": {