Lots of small improvements, websockets fallback

This commit is contained in:
Robin Linus 2015-12-23 13:57:13 +01:00
parent e5eab64c6b
commit 22be7c5cb9
35 changed files with 2672 additions and 916 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,59 @@
<link rel="import" href="p2p-network.html">
<link rel="import" href="web-socket.html">
<dom-module id="connection-wrapper">
<template>
<p2p-network id="p2p" me="{{me}}"></p2p-network>
<web-socket id="ws" me="{{me}}"></web-socket>
</template>
<script>
'use strict';
(function() {
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
var webRTCSupported = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.webkitRTCPeerConnection;
function rtcConnectionSupported(peerId) {
return webRTCSupported && (peerId.indexOf('rtc_') === 0);
}
Polymer({
is: 'connection-wrapper',
properties: {
me: {
notify: true,
value: (webRTCSupported ? 'rtc_' : 'ws_') + guid()
}
},
behaviors: [Chat.FileTransferProtocol],
_sendFile: function(toPeer, file) {
if (!rtcConnectionSupported(toPeer)) {
this.$.ws._sendFile(toPeer, file);
} else {
this.$.p2p._sendFile(toPeer, file);
}
},
_sendSystemEvent: function(toPeer, event) {
console.log('system event', toPeer, event);
if (!rtcConnectionSupported(toPeer)) {
this.$.ws._sendSystemEvent(toPeer, event);
} else {
this.$.p2p._sendSystemEvent(toPeer, event);
}
},
connectToPeer: function(toPeer, callback) {
if (!rtcConnectionSupported(toPeer)) {
callback();
} else {
this.$.p2p.connectToPeer(toPeer,callback);
}
},
});
})();
</script>
</dom-module>

View file

@ -0,0 +1,137 @@
<script>
'use strict';
window.Chat = window.Chat || {};
Chat.FileTransferProtocol = {
properties: {
loading: {
type: Boolean,
notify: true,
value: false,
observer: '_loadingChanged'
},
buddies: {
notify: true
}
},
listeners: {
'system-event': '_onSystemMsg',
'file-received': '_onFileReceived',
},
_onSystemMsg: function(event) {
var msg = event.detail;
console.log('FTP received sysMsg:', msg);
switch (msg.type) {
case 'offer':
this._onOffered(msg);
break;
case 'decline':
this._onDeclined(msg);
break;
case 'accept':
this._onAccepted(msg);
break;
case 'transfer':
this._onTransfer(msg);
break;
case 'received':
this._onReceived(msg);
break;
case 'buddies':
this._onBuddies(msg);
break;
}
},
sendFile: function(peerId, file) {
this.set('loading', true);
this.fileToSend = file;
this.fire('file-offered', {
to: peerId
});
this.connectToPeer(peerId, function() {
this._offer(peerId, file);
}.bind(this));
//set 15sec timeout
this._timeoutTimer = this.async(function() {
this._onError();
}, 15000);
},
_offer: function(toPeer, file) {
console.log('FTP offer file:', file, 'To:', toPeer);
this._sendSystemEvent(toPeer, {
type: 'offer',
name: file.name
});
},
_onOffered: function(offer) {
console.log('FTP offered file:', offer.name, 'From:', offer.from);
this.fire('file-offer', {
from: offer.from,
name: offer.name
});
},
decline: function(offer) {
this._sendSystemEvent(offer.from, {
type: 'decline',
name: offer.name
});
},
_onDeclined: function(offer) {
this.cancelAsync(this._timeoutTimer);
delete this.fileToSend;
this.set('loading', false);
this.fire('file-declined', offer);
},
accept: function(offer) {
this._sendSystemEvent(offer.from, {
type: 'accept',
name: offer.name
});
this.fire('download-started', {
from: offer.from
});
},
_onAccepted: function(offer) {
this.cancelAsync(this._timeoutTimer);
this._sendSystemEvent(offer.from, {
type: 'transfer',
name: offer.name
});
this.fire('upload-started', {
to: offer.from
});
this._sendFile(offer.from, this.fileToSend);
},
_onTransfer: function() {
this.loading = true;
},
_onFileReceived: function(event) {
var file = event.detail;
this.loading = false;
this._sendSystemEvent(file.from, {
type: 'received',
name: file.name
});
this.fire('download-complete', {
from: file.from
});
console.log('FTP received:', file);
},
_onReceived: function(offer) {
this.loading = false;
this.fire('upload-complete', offer);
},
_onError: function() {
this.loading = false;
this.fire('upload-error');
},
_loadingChanged: function(loading) {
window.anim(loading);
},
_onBuddies: function(msg) {
this.set('buddies', msg.buddies);
}
};
</script>

View file

@ -1,4 +1,5 @@
<script src="../../../bower_components/peerjs/peer.min.js"></script>
<script src="../../bower_components/peerjs/peer.min.js"></script>
<link rel="import" href="file-transfer-protocol.html">
<dom-module id="p2p-network">
<template>
</template>
@ -30,7 +31,7 @@
path: 'peerjs',
secure: true
};
this._peer = new Peer(options);
this._peer = new Peer(this.me,options);
this._peer.on('open', function(id) {
console.log('My peer ID is: ' + id);
this.set('me', id);
@ -65,12 +66,22 @@
if (c.label === 'file') {
c.on('data', function(data) {
console.log('received!', data);
console.log(data);
var dataView = new Uint8Array(data.file);
var dataBlob = new Blob([dataView]);
this.fire('file-received', {
peer: peer,
dataURI: data.dataURI,
from: peer,
blob: dataBlob,
name: data.name,
});
}.bind(this));
}
if (c.label === 'system') {
c.on('data', function(data) {
data.from = peer;
this.fire('system-event', data);
}.bind(this));
}
},
@ -78,15 +89,32 @@
function request(requestedPeer, callback) {
return function() {
//system messages channel
var s = this._peer.connect(requestedPeer, {
label: 'system'
});
s.on('open', function() {
this.connect(s);
if (callback) {
callback();
}
}.bind(this));
s.on('error', function(err) {
console.log(err);
if (err.message.indexOf('Connection is not open') > -1) {
console.err('Handle this error!!');
}
});
//files channel
var f = this._peer.connect(requestedPeer, {
label: 'file',
reliable: true
});
f.on('open', function() {
this.connect(f);
if (callback) {
callback();
}
}.bind(this));
f.on('error', function(err) {
console.log(err);
@ -98,7 +126,6 @@
callback();
return;
}
this.set('loading', true);
if (this._peerOpen) {
request(requestedPeer, callback).bind(this)();
} else {
@ -107,7 +134,7 @@
};
}()),
sendFile: function(peerId, file) {
_sendFile: function(peerId, file) {
var conns = this._peer.connections[peerId];
if (conns) {
conns.forEach(function(conn) {
@ -115,7 +142,17 @@
conn.send(file);
console.log('file send');
}
});
}.bind(this));
}
},
_sendSystemEvent: function(peerId, msg) {
var conns = this._peer.connections[peerId];
if (conns) {
conns.forEach(function(conn) {
if (conn.label === 'system') {
conn.send(msg);
}
}.bind(this));
}
}
});

View file

@ -0,0 +1,82 @@
<link rel="import" href="binaryjs.html">
<dom-module id="web-socket">
<template>
<style>
:host {
display: block;
}
</style>
</template>
<script>
'use strict';
Polymer({
is: 'web-socket',
attached: function() {
this.init();
},
init: function() {
var websocketUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + document.location.hostname + ':9001';
this.client = new BinaryClient(websocketUrl);
this.client.on('stream', function(stream, meta) {
// collect stream data
var parts = [];
stream.on('data', function(data) {
console.log('part received', meta, data);
if (data.isSystemEvent) {
if (meta) {
data.from = meta.from;
}
this.fire('system-event', data);
} else {
parts.push(data);
}
}.bind(this));
// when finished, set it as the background image
stream.on('end', function() {
var blob = new Blob(parts, {
type: meta.type
});
console.log('file received', blob, meta);
this.fire('file-received', {
blob: blob,
name: meta.name,
from: meta.from
});
}.bind(this));
}.bind(this));
this.client.on('open', function(e) {
console.log(e);
this.client.send({}, {
handshake: this.me
});
}.bind(this));
this.client.on('error', function(e) {
console.log(e);
});
this.client.on('close', function(e) {
console.log(e);
//try to reconnect after 3s
this.async(this.init, 3000);
}.bind(this));
},
_sendFile: function(toPeer, file) {
console.log('send file!', file);
this.client.send(file.file, {
name: file.file.name,
type: file.file.type,
toPeer: toPeer
});
},
connectToPeer: function(peer, callback) {
callback();
},
_sendSystemEvent: function(toPeer, event) {
console.log('system event', toPeer, event);
event.isSystemEvent = true;
this.client.send(event, {
toPeer: toPeer
});
}
});
</script>
</dom-module>