fcoin/browser/wsproxy.js
Christopher Jeffrey ee470325bf
wsproxy: minor.
2016-08-27 16:20:52 -07:00

151 lines
3.5 KiB
JavaScript

'use strict';
var http = require('http');
var net = require('net');
var IOServer = require('socket.io');
var utils = require('../lib/utils/utils');
var IP = require('../lib/utils/ip');
var networks = require('../lib/protocol/networks');
var BufferWriter = require('../lib/utils/writer');
var ports = [];
var i, type;
for (i = 0; i < networks.types.length; i++) {
type = networks.types[i];
ports.push(networks[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'
|| host.length === 0) {
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.log('Connecting to %s:%d.', host, port);
} catch (e) {
utils.error(e.message);
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', {
message: err.message,
code: err.code || null
});
});
socket.on('close', function() {
utils.log('Closing %s:%d.', host, port);
ws.emit('tcp close');
ws.disconnect();
});
ws.on('tcp data', function(data) {
if (typeof data !== 'string')
return;
socket.write(new Buffer(data, 'hex'));
});
ws.on('disconnect', function() {
socket.destroy();
});
});
});
return io;
};