2014-06-16 14:41:33 -07:00
|
|
|
'use strict';
|
2014-04-08 14:35:43 -07:00
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
var imports = require('soop').imports();
|
|
|
|
var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
|
|
|
|
var bitcore = require('bitcore');
|
|
|
|
var util = bitcore.util;
|
|
|
|
var extend = require('util')._extend;
|
2014-06-26 08:49:22 -07:00
|
|
|
var Message = require('../core/Message');
|
2014-04-08 22:20:28 -07:00
|
|
|
/*
|
|
|
|
* Emits
|
2014-05-09 10:35:57 -07:00
|
|
|
* 'connect'
|
2014-04-08 22:20:28 -07:00
|
|
|
* when network layout has change (new/lost peers, etc)
|
|
|
|
*
|
|
|
|
* 'data'
|
|
|
|
* when an unknown data type arrives
|
|
|
|
*
|
|
|
|
* Provides
|
2014-04-23 17:20:44 -07:00
|
|
|
* send(toPeerIds, {data}, cb?)
|
2014-04-08 22:20:28 -07:00
|
|
|
*
|
|
|
|
*/
|
2014-04-08 14:35:43 -07:00
|
|
|
|
2014-04-14 11:31:10 -07:00
|
|
|
function Network(opts) {
|
2014-06-24 08:36:32 -07:00
|
|
|
var self = this;
|
|
|
|
opts = opts || {};
|
|
|
|
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
|
|
|
|
this.debug = opts.debug || 3;
|
|
|
|
this.maxPeers = opts.maxPeers || 10;
|
2014-06-07 15:12:24 -07:00
|
|
|
this.reconnectAttempts = opts.reconnectAttempts || 3;
|
2014-06-24 08:36:32 -07:00
|
|
|
this.sjclParams = opts.sjclParams || {
|
|
|
|
salt: 'f28bfb49ef70573c',
|
|
|
|
iter: 500,
|
|
|
|
mode: 'ccm',
|
|
|
|
ts: parseInt(64),
|
2014-04-29 15:51:49 -07:00
|
|
|
};
|
2014-05-05 11:54:17 -07:00
|
|
|
this.opts = {};
|
2014-06-10 06:06:08 -07:00
|
|
|
['config', 'port', 'host', 'path', 'debug', 'key', 'secure'].forEach(function(k) {
|
2014-06-10 06:49:26 -07:00
|
|
|
if (opts.hasOwnProperty(k)) self.opts[k] = opts[k];
|
2014-04-17 12:58:07 -07:00
|
|
|
});
|
2014-04-24 19:13:55 -07:00
|
|
|
this.cleanUp();
|
2014-04-08 14:35:43 -07:00
|
|
|
}
|
|
|
|
|
2014-04-23 17:20:44 -07:00
|
|
|
Network.parent = EventEmitter;
|
2014-04-08 14:35:43 -07:00
|
|
|
|
2014-04-24 19:13:55 -07:00
|
|
|
Network.prototype.cleanUp = function() {
|
|
|
|
this.started = false;
|
|
|
|
this.connectedPeers = [];
|
|
|
|
this.peerId = null;
|
2014-06-08 12:59:48 -07:00
|
|
|
this.privkey = null; //TODO: hide privkey in a closure
|
2014-06-26 08:49:22 -07:00
|
|
|
this.key = null;
|
2014-04-24 19:13:55 -07:00
|
|
|
this.copayerId = null;
|
|
|
|
this.signingKey = null;
|
2014-06-24 08:36:32 -07:00
|
|
|
this.allowedCopayerIds = null;
|
|
|
|
this.isInboundPeerAuth = [];
|
|
|
|
this.copayerForPeer = {};
|
|
|
|
this.connections = {};
|
|
|
|
this.criticalErr = '';
|
2014-04-24 19:13:55 -07:00
|
|
|
if (this.peer) {
|
|
|
|
this.peer.disconnect();
|
|
|
|
this.peer.destroy();
|
2014-06-06 08:30:50 -07:00
|
|
|
this.peer.removeAllListeners();
|
2014-04-24 19:13:55 -07:00
|
|
|
this.peer = null;
|
|
|
|
}
|
|
|
|
this.closing = 0;
|
2014-06-06 08:30:50 -07:00
|
|
|
this.tries = 0;
|
2014-04-24 19:13:55 -07:00
|
|
|
};
|
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
Network.parent = EventEmitter;
|
2014-04-24 19:13:55 -07:00
|
|
|
|
2014-04-08 14:35:43 -07:00
|
|
|
// Array helpers
|
2014-04-14 11:31:10 -07:00
|
|
|
Network._arrayDiff = function(a, b) {
|
2014-04-08 14:35:43 -07:00
|
|
|
var seen = [];
|
|
|
|
var diff = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < b.length; i++)
|
|
|
|
seen[b[i]] = true;
|
|
|
|
|
|
|
|
for (var j = 0; j < a.length; j++)
|
|
|
|
if (!seen[a[j]])
|
|
|
|
diff.push(a[j]);
|
|
|
|
|
|
|
|
return diff;
|
|
|
|
};
|
|
|
|
|
2014-04-14 11:31:10 -07:00
|
|
|
Network._inArray = function(el, array) {
|
2014-04-08 14:35:43 -07:00
|
|
|
return array.indexOf(el) > -1;
|
|
|
|
};
|
|
|
|
|
2014-04-14 11:31:10 -07:00
|
|
|
Network._arrayPushOnce = function(el, array) {
|
2014-04-08 14:35:43 -07:00
|
|
|
var ret = false;
|
2014-04-14 11:31:10 -07:00
|
|
|
if (!Network._inArray(el, array)) {
|
2014-04-08 14:35:43 -07:00
|
|
|
array.push(el);
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
2014-04-14 11:31:10 -07:00
|
|
|
Network._arrayRemove = function(el, array) {
|
2014-04-08 14:35:43 -07:00
|
|
|
var pos = array.indexOf(el);
|
|
|
|
if (pos >= 0) array.splice(pos, 1);
|
|
|
|
return array;
|
|
|
|
};
|
|
|
|
|
2014-04-23 09:44:20 -07:00
|
|
|
Network.prototype.connectedCopayers = function() {
|
2014-06-24 08:36:32 -07:00
|
|
|
var ret = [];
|
|
|
|
for (var i in this.connectedPeers) {
|
|
|
|
var copayerId = this.copayerForPeer[this.connectedPeers[i]];
|
2014-04-23 09:44:20 -07:00
|
|
|
if (copayerId) ret.push(copayerId);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
2014-04-24 19:13:55 -07:00
|
|
|
Network.prototype._deletePeer = function(peerId) {
|
2014-05-01 12:40:25 -07:00
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
delete this.isInboundPeerAuth[peerId];
|
2014-05-01 12:40:25 -07:00
|
|
|
delete this.copayerForPeer[peerId];
|
|
|
|
|
2014-04-24 19:13:55 -07:00
|
|
|
if (this.connections[peerId]) {
|
|
|
|
this.connections[peerId].close();
|
|
|
|
}
|
2014-04-20 16:24:24 -07:00
|
|
|
delete this.connections[peerId];
|
2014-04-14 11:31:10 -07:00
|
|
|
this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers);
|
2014-04-24 19:13:55 -07:00
|
|
|
};
|
|
|
|
|
2014-05-09 10:44:05 -07:00
|
|
|
Network.prototype._onClose = function(peerID) {
|
|
|
|
this._deletePeer(peerID);
|
|
|
|
this.emit('disconnect', peerID);
|
2014-04-08 14:35:43 -07:00
|
|
|
};
|
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
Network.prototype.connectToCopayers = function(copayerIds) {
|
2014-04-08 14:35:43 -07:00
|
|
|
var self = this;
|
2014-06-24 08:36:32 -07:00
|
|
|
var arrayDiff = Network._arrayDiff(copayerIds, self.connectedCopayers());
|
2014-05-01 12:40:25 -07:00
|
|
|
|
2014-04-23 12:02:23 -07:00
|
|
|
arrayDiff.forEach(function(copayerId) {
|
2014-06-19 14:26:34 -07:00
|
|
|
if (self.allowedCopayerIds && !self.allowedCopayerIds[copayerId]) {
|
|
|
|
self._deletePeer(self.peerFromCopayer(copayerId));
|
2014-05-09 10:35:57 -07:00
|
|
|
} else {
|
2014-05-01 12:40:25 -07:00
|
|
|
self.connectTo(copayerId);
|
|
|
|
}
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-04-23 18:43:17 -07:00
|
|
|
Network.prototype._sendHello = function(copayerId) {
|
2014-04-23 09:44:20 -07:00
|
|
|
this.send(copayerId, {
|
2014-04-23 18:43:17 -07:00
|
|
|
type: 'hello',
|
2014-04-23 09:44:20 -07:00
|
|
|
copayerId: this.copayerId,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
Network.prototype._addConnectedCopayer = function(copayerId, isInbound) {
|
2014-04-23 12:02:23 -07:00
|
|
|
var peerId = this.peerFromCopayer(copayerId);
|
2014-06-24 08:36:32 -07:00
|
|
|
this._addCopayerMap(peerId, copayerId);
|
2014-05-01 17:48:17 -07:00
|
|
|
Network._arrayPushOnce(peerId, this.connectedPeers);
|
2014-05-09 11:02:57 -07:00
|
|
|
this.emit('connect', copayerId);
|
2014-04-23 09:44:20 -07:00
|
|
|
};
|
|
|
|
|
2014-06-26 08:49:22 -07:00
|
|
|
Network.prototype.getKey = function() {
|
|
|
|
if (!this.key) {
|
|
|
|
var key = new bitcore.Key();
|
|
|
|
key.private = new Buffer(this.privkey, 'hex');
|
|
|
|
key.regenerateSync();
|
|
|
|
this.key = key;
|
|
|
|
}
|
|
|
|
return this.key;
|
|
|
|
};
|
|
|
|
|
2014-06-26 13:58:45 -07:00
|
|
|
Network.prototype._onData = function(enc, isInbound, peerId) {
|
|
|
|
var encUint8Array = new Uint8Array(enc);
|
2014-06-18 20:12:38 -07:00
|
|
|
var encbuf = new Buffer(encUint8Array);
|
2014-06-26 08:49:22 -07:00
|
|
|
var encstr = encbuf.toString();
|
2014-06-08 12:59:48 -07:00
|
|
|
|
|
|
|
var privkey = this.privkey;
|
2014-06-26 08:49:22 -07:00
|
|
|
var key = this.getKey();
|
2014-04-25 13:36:00 -07:00
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
try {
|
2014-06-26 08:49:22 -07:00
|
|
|
var encoded = JSON.parse(encstr);
|
|
|
|
var databuf = this._decode(key, encoded);
|
|
|
|
var datastr = databuf.toString();
|
2014-06-26 13:58:45 -07:00
|
|
|
var payload = JSON.parse(datastr);
|
2014-04-09 07:05:25 -07:00
|
|
|
} catch (e) {
|
2014-04-24 19:13:55 -07:00
|
|
|
this._deletePeer(peerId);
|
2014-04-09 07:05:25 -07:00
|
|
|
return;
|
2014-04-25 13:36:00 -07:00
|
|
|
}
|
2014-04-23 18:43:17 -07:00
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
if (isInbound && payload.type === 'hello') {
|
2014-05-01 12:40:25 -07:00
|
|
|
var payloadStr = JSON.stringify(payload);
|
|
|
|
|
2014-06-26 13:58:45 -07:00
|
|
|
//ensure claimed public key is actually the public key of the peer
|
|
|
|
//e.g., their public key should hash to be their peerId
|
|
|
|
if (peerId.toString() !== this.peerFromCopayer(payload.copayerId) || peerId.toString() !== this.peerFromCopayer(encoded.pubkey)) {
|
|
|
|
this._deletePeer(peerId, 'incorrect pubkey for peerId');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-01 12:40:25 -07:00
|
|
|
if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) {
|
|
|
|
this._deletePeer(peerId);
|
|
|
|
return;
|
2014-04-23 18:43:17 -07:00
|
|
|
}
|
2014-05-01 12:40:25 -07:00
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
this._addConnectedCopayer(payload.copayerId, isInbound);
|
|
|
|
this._setInboundPeerAuth(peerId, true);
|
2014-04-23 18:43:17 -07:00
|
|
|
return;
|
2014-04-23 09:44:20 -07:00
|
|
|
}
|
2014-04-08 14:35:43 -07:00
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
if (!this.copayerForPeer[peerId] || (isInbound && !this.isInboundPeerAuth[peerId])) {
|
2014-04-24 19:13:55 -07:00
|
|
|
this._deletePeer(peerId);
|
2014-04-23 09:44:20 -07:00
|
|
|
return;
|
|
|
|
}
|
2014-04-23 18:43:17 -07:00
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
var self = this;
|
|
|
|
switch (payload.type) {
|
2014-04-08 14:35:43 -07:00
|
|
|
case 'disconnect':
|
2014-04-23 18:43:17 -07:00
|
|
|
this._onClose(peerId);
|
2014-04-08 22:20:28 -07:00
|
|
|
break;
|
|
|
|
default:
|
2014-04-23 18:43:17 -07:00
|
|
|
this.emit('data', self.copayerForPeer[peerId], payload, isInbound);
|
2014-04-08 14:35:43 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-06-07 15:12:24 -07:00
|
|
|
Network.prototype._checkAnyPeer = function(msg) {
|
2014-04-24 19:13:55 -07:00
|
|
|
if (this.connectedPeers.length === 1) {
|
|
|
|
this.emit('onlyYou');
|
|
|
|
}
|
|
|
|
};
|
2014-04-17 12:50:48 -07:00
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
Network.prototype._setupConnectionHandlers = function(dataConn, toCopayerId) {
|
2014-04-23 17:20:44 -07:00
|
|
|
var self = this;
|
2014-04-08 14:35:43 -07:00
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
var isInbound = toCopayerId ? false : true;
|
|
|
|
|
2014-04-08 14:35:43 -07:00
|
|
|
dataConn.on('open', function() {
|
2014-06-24 08:36:32 -07:00
|
|
|
if (!Network._inArray(dataConn.peer, self.connectedPeers) &&
|
|
|
|
!self.connections[dataConn.peer]) {
|
2014-04-23 12:02:23 -07:00
|
|
|
|
2014-04-20 16:24:24 -07:00
|
|
|
self.connections[dataConn.peer] = dataConn;
|
2014-04-08 14:35:43 -07:00
|
|
|
|
2014-04-28 11:02:24 -07:00
|
|
|
// The connecting peer send hello
|
2014-06-24 08:36:32 -07:00
|
|
|
if (toCopayerId) {
|
2014-05-19 16:47:28 -07:00
|
|
|
self.emit('connected');
|
2014-06-24 08:36:32 -07:00
|
|
|
self._sendHello(toCopayerId);
|
2014-05-09 11:02:57 -07:00
|
|
|
self._addConnectedCopayer(toCopayerId);
|
2014-05-01 17:48:17 -07:00
|
|
|
}
|
2014-04-08 14:35:43 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
dataConn.on('data', function(data) {
|
2014-04-23 09:44:20 -07:00
|
|
|
self._onData(data, isInbound, dataConn.peer);
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
dataConn.on('error', function(e) {
|
2014-04-20 16:24:24 -07:00
|
|
|
self._onClose(dataConn.peer);
|
|
|
|
self._checkAnyPeer();
|
2014-04-17 12:50:48 -07:00
|
|
|
self.emit('dataError');
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
dataConn.on('close', function() {
|
2014-04-12 09:37:41 -07:00
|
|
|
if (self.closing) return;
|
2014-04-20 16:24:24 -07:00
|
|
|
|
2014-04-08 14:35:43 -07:00
|
|
|
self._onClose(dataConn.peer);
|
2014-04-17 12:50:48 -07:00
|
|
|
self._checkAnyPeer();
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-04-14 11:31:10 -07:00
|
|
|
Network.prototype._setupPeerHandlers = function(openCallback) {
|
2014-04-23 17:20:44 -07:00
|
|
|
var self = this;
|
2014-04-08 14:35:43 -07:00
|
|
|
var p = this.peer;
|
|
|
|
|
2014-04-20 08:41:28 -07:00
|
|
|
p.on('open', function() {
|
|
|
|
self.connectedPeers = [self.peerId];
|
2014-06-24 08:36:32 -07:00
|
|
|
self.copayerForPeer[self.peerId] = self.copayerId;
|
2014-04-20 08:41:28 -07:00
|
|
|
return openCallback();
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
p.on('error', function(err) {
|
2014-06-07 15:12:24 -07:00
|
|
|
console.log('RECV ERROR: ', err); //TODO
|
2014-06-24 08:36:32 -07:00
|
|
|
if (!err.message.match(/Could\snot\sconnect\sto peer/)) {
|
|
|
|
self.criticalError = err.message;
|
2014-04-24 12:35:52 -07:00
|
|
|
}
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
|
2014-04-24 13:54:43 -07:00
|
|
|
p.on('connection', function(dataConn) {
|
2014-04-09 07:05:25 -07:00
|
|
|
if (self.connectedPeers.length >= self.maxPeers) {
|
|
|
|
dataConn.on('open', function() {
|
|
|
|
dataConn.close();
|
|
|
|
});
|
2014-04-23 17:20:44 -07:00
|
|
|
} else {
|
2014-05-01 17:48:17 -07:00
|
|
|
self._setInboundPeerAuth(dataConn.peer, false);
|
|
|
|
self._setupConnectionHandlers(dataConn);
|
2014-04-09 07:05:25 -07:00
|
|
|
}
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-04-23 12:02:23 -07:00
|
|
|
|
|
|
|
Network.prototype._addCopayerMap = function(peerId, copayerId) {
|
|
|
|
if (!this.copayerForPeer[peerId]) {
|
2014-06-24 08:36:32 -07:00
|
|
|
if (Object.keys(this.copayerForPeer).length < this.maxPeers) {
|
|
|
|
this.copayerForPeer[peerId] = copayerId;
|
|
|
|
} else {}
|
2014-04-23 12:02:23 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-04-24 19:13:55 -07:00
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
Network.prototype._setInboundPeerAuth = function(peerId, isAuthenticated) {
|
|
|
|
this.isInboundPeerAuth[peerId] = isAuthenticated;
|
2014-04-24 19:13:55 -07:00
|
|
|
};
|
|
|
|
|
2014-04-23 09:44:20 -07:00
|
|
|
Network.prototype.setCopayerId = function(copayerId) {
|
2014-04-20 08:41:28 -07:00
|
|
|
if (this.started) {
|
2014-04-23 17:20:44 -07:00
|
|
|
throw new Error('network already started: can not change peerId')
|
2014-04-20 08:41:28 -07:00
|
|
|
}
|
2014-04-23 09:44:20 -07:00
|
|
|
this.copayerId = copayerId;
|
2014-06-24 08:36:32 -07:00
|
|
|
this.copayerIdBuf = new Buffer(copayerId, 'hex');
|
2014-04-23 09:44:20 -07:00
|
|
|
this.peerId = this.peerFromCopayer(this.copayerId);
|
2014-06-24 08:36:32 -07:00
|
|
|
this._addCopayerMap(this.peerId, copayerId);
|
2014-04-20 08:41:28 -07:00
|
|
|
};
|
|
|
|
|
2014-04-23 18:43:17 -07:00
|
|
|
|
2014-06-03 07:54:07 -07:00
|
|
|
// TODO cache this.
|
2014-04-23 09:44:20 -07:00
|
|
|
Network.prototype.peerFromCopayer = function(hex) {
|
2014-04-24 19:13:55 -07:00
|
|
|
var SIN = bitcore.SIN;
|
2014-06-24 08:36:32 -07:00
|
|
|
return new SIN(new Buffer(hex, 'hex')).toString();
|
2014-04-23 09:44:20 -07:00
|
|
|
};
|
2014-04-20 08:41:28 -07:00
|
|
|
|
2014-04-23 18:43:17 -07:00
|
|
|
Network.prototype.start = function(opts, openCallback) {
|
2014-04-18 14:25:51 -07:00
|
|
|
opts = opts || {};
|
2014-04-24 19:13:55 -07:00
|
|
|
|
|
|
|
if (this.started) return openCallback();
|
|
|
|
|
2014-06-18 20:12:38 -07:00
|
|
|
if (!this.privkey)
|
|
|
|
this.privkey = opts.privkey;
|
|
|
|
|
2014-04-24 19:13:55 -07:00
|
|
|
this.maxPeers = opts.maxPeers || this.maxPeers;
|
2014-04-16 18:12:30 -07:00
|
|
|
|
2014-05-22 19:28:26 -07:00
|
|
|
if (opts.token)
|
|
|
|
this.opts.token = opts.token;
|
|
|
|
|
2014-04-24 12:35:52 -07:00
|
|
|
if (!this.copayerId)
|
2014-04-23 18:43:17 -07:00
|
|
|
this.setCopayerId(opts.copayerId);
|
2014-04-23 09:44:20 -07:00
|
|
|
|
2014-06-06 08:30:50 -07:00
|
|
|
var self = this;
|
2014-06-24 08:36:32 -07:00
|
|
|
var setupPeer = function() {
|
2014-06-06 08:30:50 -07:00
|
|
|
if (self.connectedPeers.length > 0) return; // Already connected!
|
|
|
|
if (self.peer) {
|
|
|
|
self.peer.destroy();
|
|
|
|
self.peer.removeAllListeners();
|
|
|
|
}
|
|
|
|
|
2014-06-07 15:12:24 -07:00
|
|
|
if (!self.criticalError && self.tries < self.reconnectAttempts) {
|
2014-06-06 08:30:50 -07:00
|
|
|
self.tries++;
|
|
|
|
self.peer = new Peer(self.peerId, self.opts);
|
|
|
|
self.started = true;
|
|
|
|
self._setupPeerHandlers(openCallback);
|
|
|
|
setTimeout(setupPeer, 3000); // Schedule retry
|
|
|
|
return;
|
|
|
|
}
|
2014-06-07 15:12:24 -07:00
|
|
|
if (self.criticalError && self.criticalError.match(/taken/)) {
|
2014-06-24 08:36:32 -07:00
|
|
|
self.criticalError = ' Looks like you are already connected to this wallet please close all other Copay Wallets '
|
2014-06-07 15:12:24 -07:00
|
|
|
}
|
|
|
|
self.emit('serverError', self.criticalError);
|
2014-06-06 08:30:50 -07:00
|
|
|
self.cleanUp();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.tries = 0;
|
|
|
|
setupPeer();
|
|
|
|
};
|
2014-04-23 09:44:20 -07:00
|
|
|
|
2014-04-24 12:07:49 -07:00
|
|
|
Network.prototype.getOnlinePeerIDs = function() {
|
|
|
|
return this.connectedPeers;
|
|
|
|
};
|
|
|
|
|
|
|
|
Network.prototype.getPeer = function() {
|
|
|
|
return this.peer;
|
2014-04-23 18:43:17 -07:00
|
|
|
};
|
|
|
|
|
2014-06-26 08:49:22 -07:00
|
|
|
Network.prototype._encode = function(topubkey, fromkey, payload) {
|
|
|
|
var encoded = Message.encode(topubkey, fromkey, payload);
|
|
|
|
return encoded;
|
2014-04-29 15:51:49 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-06-26 08:49:22 -07:00
|
|
|
Network.prototype._decode = function(key, encoded) {
|
|
|
|
var payload = Message.decode(key, encoded);
|
|
|
|
return payload;
|
2014-04-29 15:51:49 -07:00
|
|
|
};
|
2014-04-25 13:36:00 -07:00
|
|
|
|
2014-06-26 13:58:45 -07:00
|
|
|
Network.prototype._sendToOne = function(copayerId, payload, cb) {
|
2014-04-23 09:44:20 -07:00
|
|
|
var peerId = this.peerFromCopayer(copayerId);
|
2014-04-08 14:35:43 -07:00
|
|
|
if (peerId !== this.peerId) {
|
2014-04-20 16:24:24 -07:00
|
|
|
var dataConn = this.connections[peerId];
|
|
|
|
if (dataConn) {
|
2014-04-30 09:02:40 -07:00
|
|
|
dataConn.send(payload);
|
2014-04-20 16:24:24 -07:00
|
|
|
}
|
2014-04-08 14:35:43 -07:00
|
|
|
}
|
|
|
|
if (typeof cb === 'function') cb();
|
|
|
|
};
|
|
|
|
|
2014-04-23 18:43:17 -07:00
|
|
|
Network.prototype.send = function(copayerIds, payload, cb) {
|
2014-06-08 12:59:48 -07:00
|
|
|
if (!payload) return cb();
|
2014-06-09 13:37:06 -07:00
|
|
|
|
2014-06-24 08:36:32 -07:00
|
|
|
var self = this;
|
2014-04-23 09:44:20 -07:00
|
|
|
if (!copayerIds) {
|
|
|
|
copayerIds = this.connectedCopayers();
|
2014-04-23 18:43:17 -07:00
|
|
|
payload.isBroadcast = 1;
|
2014-04-08 22:20:28 -07:00
|
|
|
}
|
|
|
|
|
2014-06-16 15:35:54 -07:00
|
|
|
if (typeof copayerIds === 'string')
|
|
|
|
copayerIds = [copayerIds];
|
|
|
|
|
2014-04-25 13:36:00 -07:00
|
|
|
var payloadStr = JSON.stringify(payload);
|
2014-06-08 12:59:48 -07:00
|
|
|
var payloadBuf = new Buffer(payloadStr);
|
2014-06-16 15:35:54 -07:00
|
|
|
|
|
|
|
var l = copayerIds.length;
|
|
|
|
var i = 0;
|
|
|
|
copayerIds.forEach(function(copayerId) {
|
|
|
|
var copayerIdBuf = new Buffer(copayerId, 'hex');
|
2014-06-26 08:49:22 -07:00
|
|
|
var encPayload = self._encode(copayerIdBuf, self.getKey(), payloadBuf);
|
2014-06-26 13:58:45 -07:00
|
|
|
self._sendToOne(copayerId, encPayload, function() {
|
2014-06-16 15:35:54 -07:00
|
|
|
if (++i === l && typeof cb === 'function') cb();
|
2014-04-08 14:35:43 -07:00
|
|
|
});
|
2014-06-16 15:35:54 -07:00
|
|
|
});
|
2014-04-08 14:35:43 -07:00
|
|
|
};
|
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
|
2014-06-03 07:54:07 -07:00
|
|
|
Network.prototype.isOnline = function() {
|
|
|
|
return !!this.peer;
|
|
|
|
};
|
|
|
|
|
2014-04-23 09:44:20 -07:00
|
|
|
Network.prototype.connectTo = function(copayerId) {
|
2014-04-08 14:35:43 -07:00
|
|
|
var self = this;
|
2014-04-23 12:02:23 -07:00
|
|
|
|
2014-05-01 17:48:17 -07:00
|
|
|
var peerId = this.peerFromCopayer(copayerId);
|
2014-04-08 14:35:43 -07:00
|
|
|
var dataConn = this.peer.connect(peerId, {
|
|
|
|
serialization: 'none',
|
|
|
|
reliable: true,
|
|
|
|
});
|
2014-05-01 17:48:17 -07:00
|
|
|
self._setupConnectionHandlers(dataConn, copayerId);
|
2014-04-08 14:35:43 -07:00
|
|
|
};
|
|
|
|
|
2014-04-24 19:13:55 -07:00
|
|
|
Network.prototype.lockIncommingConnections = function(allowedCopayerIdsArray) {
|
2014-06-24 08:36:32 -07:00
|
|
|
this.allowedCopayerIds = {};
|
|
|
|
for (var i in allowedCopayerIdsArray) {
|
|
|
|
this.allowedCopayerIds[allowedCopayerIdsArray[i]] = true;
|
2014-04-24 12:35:52 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-04-18 14:25:51 -07:00
|
|
|
Network.prototype.disconnect = function(cb, forced) {
|
2014-04-08 14:35:43 -07:00
|
|
|
var self = this;
|
2014-04-12 09:37:41 -07:00
|
|
|
self.closing = 1;
|
2014-06-24 08:36:32 -07:00
|
|
|
self.send(null, {
|
|
|
|
type: 'disconnect'
|
|
|
|
}, function() {
|
2014-04-24 19:13:55 -07:00
|
|
|
self.cleanUp();
|
2014-04-24 13:54:43 -07:00
|
|
|
if (typeof cb === 'function') cb();
|
|
|
|
});
|
2014-04-08 14:35:43 -07:00
|
|
|
};
|
|
|
|
|
2014-04-14 11:31:10 -07:00
|
|
|
module.exports = require('soop')(Network);
|