148 lines
3.4 KiB
JavaScript
148 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
var http = require('http');
|
|
var net = require('net');
|
|
var IOServer = require('socket.io');
|
|
var utils = require('../lib/bcoin/utils');
|
|
var IP = require('../lib/bcoin/ip');
|
|
var network = require('../lib/bcoin/protocol/network');
|
|
var BufferWriter = require('../lib/bcoin/writer');
|
|
var ports = [];
|
|
var i, type;
|
|
|
|
for (i = 0; i < network.types.length; i++) {
|
|
type = network.types[i];
|
|
ports.push(network[type].port);
|
|
}
|
|
|
|
module.exports = function wsproxy(options) {
|
|
var target, io;
|
|
|
|
if (!options)
|
|
options = {};
|
|
|
|
target = new Buffer(
|
|
'0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
|
'hex');
|
|
|
|
io = new IOServer();
|
|
|
|
io.on('error', function(err) {
|
|
utils.error(err.stack + '');
|
|
});
|
|
|
|
io.on('connection', function(ws) {
|
|
var snonce = utils.nonce().toArrayLike(Buffer, 'be', 8);
|
|
var socket, pow;
|
|
|
|
ws.emit('info', {
|
|
pow: !!options.pow,
|
|
snonce: snonce.toString('hex'),
|
|
target: target.toString('hex')
|
|
});
|
|
|
|
ws.on('error', function(err) {
|
|
utils.error(err.stack + '');
|
|
});
|
|
|
|
ws.on('tcp connect', function(port, host, nonce) {
|
|
if (socket)
|
|
return;
|
|
|
|
if (!utils.isNumber(port)
|
|
|| typeof host !== 'string') {
|
|
utils.error('Client gave bad arguments.');
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
if (options.pow) {
|
|
if (!utils.isNumber(nonce)) {
|
|
utils.error('Client did not solve proof of work.');
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
pow = new BufferWriter();
|
|
pow.writeU32(nonce);
|
|
pow.writeBytes(snonce);
|
|
pow.writeU32(port);
|
|
pow.writeString(host, 'ascii');
|
|
pow = pow.render();
|
|
|
|
if (utils.cmp(utils.dsha256(pow), target) >= 0) {
|
|
utils.error('Client did not solve proof of work.');
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!/^[a-zA-Z0-9\.:\-]+$/.test(host)) {
|
|
utils.error('Client gave a bad host.');
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
if (IP.isPrivate(host)) {
|
|
utils.error('Client is trying to connect to a private ip.');
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
if (ports.indexOf(port) === -1) {
|
|
utils.error('Client is trying to connect to a non-bitcoin port.');
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
socket = net.connect(port, host);
|
|
utils.error('Connecting to %s:%d.', host, port);
|
|
} catch (e) {
|
|
utils.error('Closing %s:%d.', host, port);
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
socket.on('connect', function() {
|
|
ws.emit('tcp connect');
|
|
});
|
|
|
|
socket.on('data', function(data) {
|
|
ws.emit('tcp data', data.toString('hex'));
|
|
});
|
|
|
|
socket.on('error', function(err) {
|
|
ws.emit('tcp error', err.message);
|
|
});
|
|
|
|
socket.on('close', function() {
|
|
utils.error('Closing %s:%d.', host, port);
|
|
ws.emit('tcp close');
|
|
ws.disconnect();
|
|
});
|
|
|
|
ws.on('tcp data', function(data) {
|
|
socket.write(new Buffer(data, 'hex'));
|
|
});
|
|
|
|
ws.on('disconnect', function() {
|
|
socket.destroy();
|
|
});
|
|
|
|
ws.on('close', function() {
|
|
socket.destroy();
|
|
});
|
|
});
|
|
});
|
|
|
|
return io;
|
|
};
|