Merge pull request #256 from matiu/feature/reconnect-simpler-peer-mgmt

better peer management / peer reconection
This commit is contained in:
Mario Colque 2014-05-01 22:22:44 -03:00
commit aa0ed193fd
4 changed files with 41 additions and 74 deletions

View File

@ -45,6 +45,7 @@ angular.module('copay.header').controller('HeaderController',
$scope.refresh = function() { $scope.refresh = function() {
controllerUtils.updateBalance(function() { controllerUtils.updateBalance(function() {
w.connectToAll();
$rootScope.$digest(); $rootScope.$digest();
}); });
}; };

View File

@ -49,6 +49,16 @@ Wallet.getRandomId = function() {
return r; return r;
}; };
Wallet.prototype.connectToAll = function() {
var all = this.publicKeyRing.getAllCopayerIds();
this.network.connectToCopayers(all);
if (this.firstCopayerId) {
this.sendWalletReady(this.firstCopayerId);
this.firstCopayerId = null;
}
this.emit('refresh');
};
Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
this.log('RECV PUBLICKEYRING:', data); this.log('RECV PUBLICKEYRING:', data);
@ -57,10 +67,12 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
var hasChanged = pkr.merge(inPKR, true); var hasChanged = pkr.merge(inPKR, true);
if (hasChanged) { if (hasChanged) {
this.connectToAll();
if (this.publicKeyRing.isComplete()) { if (this.publicKeyRing.isComplete()) {
this._lockIncomming(); this._lockIncomming();
} }
this.log('### BROADCASTING PKR'); this.log('### BROADCASTING PKR');
recipients = null; recipients = null;
this.sendPublicKeyRing(recipients); this.sendPublicKeyRing(recipients);
} }
@ -92,7 +104,6 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) {
this.log('badMessage FROM:', senderId); //TODO this.log('badMessage FROM:', senderId); //TODO
return; return;
} }
this.log('[Wallet.js.98]', data.type); //TODO
switch (data.type) { switch (data.type) {
// This handler is repeaded on WalletFactory (#join). TODO // This handler is repeaded on WalletFactory (#join). TODO
case 'walletId': case 'walletId':
@ -196,17 +207,7 @@ Wallet.prototype.netStart = function() {
net.start(startOpts, function() { net.start(startOpts, function() {
self.emit('created', net.getPeer()); self.emit('created', net.getPeer());
for (var i = 0; i < self.publicKeyRing.registeredCopayers(); i++) { self.connectToAll();
var otherId = self.getCopayerId(i);
if (otherId !== myId) {
net.connectTo(otherId);
}
if (self.firstCopayerId) {
self.sendWalletReady(self.firstCopayerId);
self.firstCopayerId = null;
}
self.emit('refresh');
}
}); });
}; };
@ -559,10 +560,6 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
return true; return true;
}; };
Wallet.prototype.connectTo = function(peerId) {
throw new Error('Wallet.connectTo.. not yet implemented!');
};
Wallet.prototype.disconnect = function() { Wallet.prototype.disconnect = function() {
this.log('## DISCONNECTING'); this.log('## DISCONNECTING');
this.network.disconnect(); this.network.disconnect();

View File

@ -136,7 +136,6 @@ WalletFactory.prototype.open = function(walletId, opts) {
opts = opts || {}; opts = opts || {};
opts.id = walletId; opts.id = walletId;
opts.verbose = this.verbose; opts.verbose = this.verbose;
this.storage._setPassphrase(opts.passphrase); this.storage._setPassphrase(opts.passphrase);
var w = this.read(walletId) || this.create(opts); var w = this.read(walletId) || this.create(opts);

View File

@ -48,7 +48,7 @@ Network.prototype.cleanUp = function() {
this.copayerId = null; this.copayerId = null;
this.signingKey = null; this.signingKey = null;
this.allowedCopayerIds=null; this.allowedCopayerIds=null;
this.authenticatedPeers=[]; this.isInboundPeerAuth=[];
this.copayerForPeer={}; this.copayerForPeer={};
this.connections={}; this.connections={};
if (this.peer) { if (this.peer) {
@ -108,7 +108,7 @@ Network.prototype.connectedCopayers = function() {
Network.prototype._deletePeer = function(peerId) { Network.prototype._deletePeer = function(peerId) {
console.log('### Deleting connection from peer:', peerId); console.log('### Deleting connection from peer:', peerId);
this._setPeerAuthenticated(peerId, 0); delete this.isInboundPeerAuth[peerId];
delete this.copayerForPeer[peerId]; delete this.copayerForPeer[peerId];
if (this.connections[peerId]) { if (this.connections[peerId]) {
@ -123,8 +123,7 @@ Network.prototype._onClose = function(peerId) {
this._notifyNetworkChange(); this._notifyNetworkChange();
}; };
// TODO RM THIS! (connect from pub key ring) Network.prototype.connectToCopayers = function(copayerIds) {
Network.prototype._connectToCopayers = function(copayerIds) {
var self = this; var self = this;
var arrayDiff= Network._arrayDiff(copayerIds, this.connectedCopayers()); var arrayDiff= Network._arrayDiff(copayerIds, this.connectedCopayers());
@ -148,30 +147,12 @@ Network.prototype._sendHello = function(copayerId) {
}); });
}; };
Network.prototype._sendCopayers = function(copayerIds) { Network.prototype._addConnectedCopayer = function(copayerId, isInbound) {
console.log('### SENDING PEER LIST: ', this.connectedPeers,this.connectedCopayers(), ' TO ', copayerIds?copayerIds: 'ALL');
this.send(copayerIds, {
type: 'copayers',
copayers: this.connectedCopayers(),
});
};
Network.prototype._addCopayer = function(copayerId, isInbound) {
var peerId = this.peerFromCopayer(copayerId); var peerId = this.peerFromCopayer(copayerId);
this._addCopayerMap(peerId,copayerId); this._addCopayerMap(peerId,copayerId);
var hasChanged = Network._arrayPushOnce(peerId, this.connectedPeers); Network._arrayPushOnce(peerId, this.connectedPeers);
if (isInbound && hasChanged) {
this._sendCopayers(); //broadcast peer list
}
else {
if (isInbound) {
this._sendCopayers(copayerId);
}
}
}; };
Network.prototype._onData = function(encStr, isInbound, peerId) { Network.prototype._onData = function(encStr, isInbound, peerId) {
var sig, payload; var sig, payload;
@ -187,7 +168,7 @@ Network.prototype._onData = function(encStr, isInbound, peerId) {
console.log('### RECEIVED INBOUND?:%s TYPE: %s FROM %s', console.log('### RECEIVED INBOUND?:%s TYPE: %s FROM %s',
isInbound, payload.type, peerId, payload); isInbound, payload.type, peerId, payload);
if(payload.type === 'hello') { if(isInbound && payload.type === 'hello') {
var payloadStr = JSON.stringify(payload); var payloadStr = JSON.stringify(payload);
if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) { if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) {
@ -198,28 +179,20 @@ Network.prototype._onData = function(encStr, isInbound, peerId) {
} }
console.log('#### Peer sent hello. Setting it up.'); //TODO console.log('#### Peer sent hello. Setting it up.'); //TODO
this._setPeerAuthenticated(peerId, 1); this._addConnectedCopayer(payload.copayerId, isInbound);
this._addCopayer(payload.copayerId, isInbound); this._setInboundPeerAuth(peerId, true);
this._notifyNetworkChange( isInbound ? payload.copayerId : null); this._notifyNetworkChange( isInbound ? payload.copayerId : null);
this.emit('open'); this.emit('open');
return; return;
} }
//copayerForPeer is populated also in 'copayers' message, so we need authenticatedPeer if ( !this.copayerForPeer[peerId] || (isInbound && !this.isInboundPeerAuth[peerId]) ) {
if (isInbound && (!this.copayerForPeer[peerId] || !this.authenticatedPeers[peerId])) {
this._deletePeer(peerId); this._deletePeer(peerId);
return; return;
} }
var copayerIdBuf = new Buffer(this.copayerForPeer[peerId],'hex');
var self=this; var self=this;
switch(payload.type) { switch(payload.type) {
case 'copayers':
//TODO is this really necesarry??? => NO connect from pubkeyring.
this._addCopayer(this.copayerForPeer[peerId], false);
this._connectToCopayers(payload.copayers);
this._notifyNetworkChange();
break;
case 'disconnect': case 'disconnect':
this._onClose(peerId); this._onClose(peerId);
break; break;
@ -239,13 +212,14 @@ Network.prototype._checkAnyPeer = function() {
} }
}; };
Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) { Network.prototype._setupConnectionHandlers = function(dataConn, toCopayerId) {
var self = this; var self = this;
var isInbound = toCopayerId ? false : true;
dataConn.on('open', function() { dataConn.on('open', function() {
self._setPeerAuthenticated(dataConn.peer, 0); if (!Network._inArray(dataConn.peer, self.connectedPeers) &&
if (!Network._inArray(dataConn.peer, self.connectedPeers) !self.connections[dataConn.peer]) {
&& !self.connections[dataConn.peer]) {
self.connections[dataConn.peer] = dataConn; self.connections[dataConn.peer] = dataConn;
@ -253,8 +227,10 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
dataConn.peer, isInbound); dataConn.peer, isInbound);
// The connecting peer send hello // The connecting peer send hello
if(!isInbound) if(toCopayerId) {
self._sendHello(self.copayerForPeer[dataConn.peer]); self._addConnectedCopayer(toCopayerId);
self._sendHello(toCopayerId);
}
} }
}); });
@ -289,7 +265,6 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
p.on('open', function() { p.on('open', function() {
self.connectedPeers = [self.peerId]; self.connectedPeers = [self.peerId];
self.copayerForPeer[self.peerId]= self.copayerId; self.copayerForPeer[self.peerId]= self.copayerId;
return openCallback(); return openCallback();
}); });
@ -310,8 +285,8 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
dataConn.close(); dataConn.close();
}); });
} else { } else {
self._setPeerAuthenticated(dataConn.peer, 0); self._setInboundPeerAuth(dataConn.peer, false);
self._setupConnectionHandlers(dataConn, true); self._setupConnectionHandlers(dataConn);
} }
}); });
}; };
@ -330,8 +305,8 @@ Network.prototype._addCopayerMap = function(peerId, copayerId) {
}; };
Network.prototype._setPeerAuthenticated = function(peerId, isAuthenticated) { Network.prototype._setInboundPeerAuth = function(peerId, isAuthenticated) {
this.authenticatedPeers[peerId] = isAuthenticated; this.isInboundPeerAuth[peerId] = isAuthenticated;
}; };
Network.prototype.setCopayerId = function(copayerId) { Network.prototype.setCopayerId = function(copayerId) {
@ -346,6 +321,7 @@ Network.prototype.setCopayerId = function(copayerId) {
Network.prototype.peerFromCopayer = function(hex) { Network.prototype.peerFromCopayer = function(hex) {
// TODO cache this.
var SIN = bitcore.SIN; var SIN = bitcore.SIN;
return new SIN(new Buffer(hex,'hex')).toString(); return new SIN(new Buffer(hex,'hex')).toString();
}; };
@ -363,13 +339,8 @@ Network.prototype.start = function(opts, openCallback) {
console.log('CREATING PEER INSTANCE:', this.peerId); //TODO console.log('CREATING PEER INSTANCE:', this.peerId); //TODO
this.peer = new Peer(this.peerId, this.opts); this.peer = new Peer(this.peerId, this.opts);
this._setupPeerHandlers(openCallback);
opts.connectedPeers = opts.connectedPeers || [];
for (var i = 0; i<opts.connectedPeers.length; i++) {
var otherPeerId = opts.connectedPeers[i];
this.connectTo(otherPeerId);
}
this.started = true; this.started = true;
this._setupPeerHandlers(openCallback);
}; };
@ -441,18 +412,17 @@ Network.prototype.send = function(copayerIds, payload, cb) {
self._sendToOne(copayerIds, encPayload, sig, cb); self._sendToOne(copayerIds, encPayload, sig, cb);
}; };
Network.prototype.connectTo = function(copayerId) { Network.prototype.connectTo = function(copayerId) {
var self = this; var self = this;
var peerId = this.peerFromCopayer(copayerId);
this._addCopayerMap(peerId,copayerId);
var peerId = this.peerFromCopayer(copayerId);
console.log('### STARTING CONNECTION TO:\n\t'+ peerId+"\n\t"+ copayerId); console.log('### STARTING CONNECTION TO:\n\t'+ peerId+"\n\t"+ copayerId);
var dataConn = this.peer.connect(peerId, { var dataConn = this.peer.connect(peerId, {
serialization: 'none', serialization: 'none',
reliable: true, reliable: true,
}); });
self._setupConnectionHandlers(dataConn, copayerId);
self._setupConnectionHandlers(dataConn, false);
}; };
Network.prototype.lockIncommingConnections = function(allowedCopayerIdsArray) { Network.prototype.lockIncommingConnections = function(allowedCopayerIdsArray) {