diff --git a/dist/netflux.es5.js b/dist/netflux.es5.js index 39905129..6f69f752 100644 --- a/dist/netflux.es5.js +++ b/dist/netflux.es5.js @@ -11516,6 +11516,45 @@ return /******/ (function(modules) { // webpackBootstrap */ var INIT_CHANNEL_PONG = 10; + var WebChannelGate = function () { + function WebChannelGate(action) { + _classCallCheck(this, WebChannelGate); + + this.door = null; + this.accessData = null; + this.action = action; + } + + _createClass(WebChannelGate, [{ + key: 'getAccessData', + value: function getAccessData() { + return this.accessData; + } + }, { + key: 'isOpen', + value: function isOpen() { + return this.door !== null; + } + }, { + key: 'setOpen', + value: function setOpen(door, accessData, action) { + this.door = door; + this.door.onclose = this.action; + this.accessData = accessData; + } + }, { + key: 'close', + value: function close() { + if (this.isOpen()) { + this.door.close(); + this.door = null; + } + } + }]); + + return WebChannelGate; + }(); + /** * This class is an API starting point. It represents a group of collaborators * also called peers. Each peer can send/receive broadcast as well as personal @@ -11524,6 +11563,7 @@ return /******/ (function(modules) { // webpackBootstrap * preserving the current *WebChannel* structure (network topology). */ + var WebChannel = function () { /** @@ -11540,6 +11580,8 @@ return /******/ (function(modules) { // webpackBootstrap */ function WebChannel() { + var _this = this; + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; _classCallCheck(this, WebChannel); @@ -11594,8 +11636,13 @@ return /******/ (function(modules) { // webpackBootstrap this.myId = this.generateId(); this.onJoining = function (id) {}; - this.onMessage = function (id, msg) {}; + this.onMessage = function (id, msg, isBroadcast) {}; this.onLeaving = function (id) {}; + this.onClose = function (closeEvt) {}; + + this.gate = new WebChannelGate(function (closeEvt) { + return _this.onClose(closeEvt); + }); } /** Leave `WebChannel`. No longer can receive and send messages to the group. */ @@ -11611,6 +11658,7 @@ return /******/ (function(modules) { // webpackBootstrap c.close(); }); this.channels.clear(); + this.gate.close(); } } @@ -11623,11 +11671,11 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'send', value: function send(data) { - var _this = this; + var _this2 = this; if (this.channels.size !== 0) { formatter.handleUserMessage(data, this.myId, null, function (dataChunk) { - _this.manager.broadcast(_this, dataChunk); + _this2.manager.broadcast(_this2, dataChunk); }); } } @@ -11642,11 +11690,11 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'sendTo', value: function sendTo(id, data) { - var _this2 = this; + var _this3 = this; if (this.channels.size !== 0) { formatter.handleUserMessage(data, this.myId, id, function (dataChunk) { - _this2.manager.sendTo(id, _this2, dataChunk); + _this3.manager.sendTo(id, _this3, dataChunk); }, false); } } @@ -11662,7 +11710,7 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'openForJoining', value: function openForJoining() { - var _this3 = this; + var _this4 = this; var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; @@ -11670,24 +11718,25 @@ return /******/ (function(modules) { // webpackBootstrap var cBuilder = (0, _serviceProvider.provide)(settings.connector, settings); return cBuilder.open(this.generateKey(), function (channel) { - _this3.initChannel(channel, false).then(function (channel) { + _this4.initChannel(channel, false).then(function (channel) { // console.log('INITIATOR is adding: ' + channel.peerId) - var jp = _this3.addJoiningPeer(channel.peerId, _this3.myId, channel); - _this3.manager.broadcast(_this3, formatter.msg(JOIN_NEW_MEMBER, { id: channel.peerId, intermediaryId: _this3.myId })); + var jp = _this4.addJoiningPeer(channel.peerId, _this4.myId, channel); + _this4.manager.broadcast(_this4, formatter.msg(JOIN_NEW_MEMBER, { id: channel.peerId, intermediaryId: _this4.myId })); channel.send(formatter.msg(JOIN_INIT, { - manager: _this3.settings.topology, + manager: _this4.settings.topology, id: channel.peerId, - intermediaryId: _this3.myId })); - _this3.manager.add(channel).then(function () { + intermediaryId: _this4.myId })); + _this4.manager.add(channel).then(function () { return channel.send(formatter.msg(JOIN_FINILIZE)); }).catch(function (msg) { - _this3.manager.broadcast(_this3, formatter(REMOVE_NEW_MEMBER, { id: channel.peerId })); - _this3.removeJoiningPeer(jp.id); + _this4.manager.broadcast(_this4, formatter(REMOVE_NEW_MEMBER, { id: channel.peerId })); + _this4.removeJoiningPeer(jp.id); }); }); }).then(function (data) { - _this3.webRTCOpen = data.socket; - return { key: data.key, url: data.url }; + var accessData = { key: data.key, url: data.url }; + _this4.gate.setOpen(data.socket, accessData); + return accessData; }); } @@ -11698,9 +11747,17 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'closeForJoining', value: function closeForJoining() { - if (Reflect.has(this, 'webRTCOpen')) { - this.webRTCOpen.close(); - } + this.gate.close(); + } + }, { + key: 'isOpen', + value: function isOpen() { + return this.gate.isOpen(); + } + }, { + key: 'getAccess', + value: function getAccess() { + return this.gate.getAccessData(); } /** @@ -11714,7 +11771,7 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'join', value: function join(key) { - var _this4 = this; + var _this5 = this; var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; @@ -11723,26 +11780,15 @@ return /******/ (function(modules) { // webpackBootstrap console.log('CONNECTOR webchannel: ' + this.settings.connector + ' --- ' + settings.connector); var cBuilder = (0, _serviceProvider.provide)(settings.connector, settings); return new Promise(function (resolve, reject) { - _this4.onJoin = function () { - return resolve(_this4); + _this5.onJoin = function () { + return resolve(_this5); }; cBuilder.join(key).then(function (channel) { - return _this4.initChannel(channel, true); + return _this5.initChannel(channel, true); }).catch(reject); }); } - /** - * - * - * @private - * @return {type} description - */ - - }, { - key: 'isInviting', - value: function isInviting() {} - /** * has - description * @@ -11832,12 +11878,12 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'onChannelMessage', value: function onChannelMessage(channel, data) { - var _this5 = this; + var _this6 = this; var header = formatter.readHeader(data); if (header.code === USER_DATA) { formatter.readUserMessage(this.id, header.senderId, data, function (fullData, isBroadcast) { - _this5.onMessage(header.senderId, fullData, isBroadcast); + _this6.onMessage(header.senderId, fullData, isBroadcast); }); } else { var msg = formatter.readInternalMessage(data); @@ -11923,15 +11969,15 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'initChannel', value: function initChannel(ch, isInitiator) { - var _this6 = this; + var _this7 = this; var id = arguments.length <= 2 || arguments[2] === undefined ? -1 : arguments[2]; return new Promise(function (resolve, reject) { if (id === -1) { - id = _this6.generateId(); + id = _this7.generateId(); } - var channel = new _Channel2.default(ch, _this6, id); + var channel = new _Channel2.default(ch, _this7, id); // TODO: treat the case when the 'ping' or 'pong' message has not been received if (isInitiator) { channel.config(); @@ -11962,11 +12008,11 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'joinSuccess', value: function joinSuccess(id) { - var _this7 = this; + var _this8 = this; var jp = this.getJoiningPeer(id); jp.channelsToAdd.forEach(function (c) { - _this7.channels.add(c); + _this8.channels.add(c); }); // TODO: handle channels which should be closed & removed // this.joiningPeers.delete(jp) diff --git a/dist/netflux.js b/dist/netflux.js index aa84f156..00414c79 100644 --- a/dist/netflux.js +++ b/dist/netflux.js @@ -2386,6 +2386,36 @@ */ const INIT_CHANNEL_PONG = 10 + + class WebChannelGate { + constructor (action) { + this.door = null + this.accessData = null + this.action = action + } + + getAccessData () { + return this.accessData + } + + isOpen () { + return this.door !== null + } + + setOpen (door, accessData, action) { + this.door = door + this.door.onclose = this.action + this.accessData = accessData + } + + close () { + if (this.isOpen()) { + this.door.close() + this.door = null + } + } + } + /** * This class is an API starting point. It represents a group of collaborators * also called peers. Each peer can send/receive broadcast as well as personal @@ -2458,8 +2488,11 @@ this.myId = this.generateId() this.onJoining = (id) => {} - this.onMessage = (id, msg) => {} + this.onMessage = (id, msg, isBroadcast) => {} this.onLeaving = (id) => {} + this.onClose = (closeEvt) => {} + + this.gate = new WebChannelGate((closeEvt) => this.onClose(closeEvt)) } /** Leave `WebChannel`. No longer can receive and send messages to the group. */ @@ -2471,6 +2504,7 @@ c.close() }) this.channels.clear() + this.gate.close() } } @@ -2535,8 +2569,9 @@ }) }) }).then((data) => { - this.webRTCOpen = data.socket - return {key: data.key, url: data.url} + let accessData = {key: data.key, url: data.url} + this.gate.setOpen(data.socket, accessData) + return accessData }) } @@ -2544,9 +2579,15 @@ * Prevent other peers to join the `WebChannel` even if they have a key. */ closeForJoining () { - if (Reflect.has(this, 'webRTCOpen')) { - this.webRTCOpen.close() - } + this.gate.close() + } + + isOpen () { + return this.gate.isOpen() + } + + getAccess () { + return this.gate.getAccessData() } /** @@ -2569,14 +2610,6 @@ }) } - /** - * - * - * @private - * @return {type} description - */ - isInviting () {} - /** * has - description * diff --git a/src/WebChannel.js b/src/WebChannel.js index 16813411..fbbbf905 100644 --- a/src/WebChannel.js +++ b/src/WebChannel.js @@ -57,6 +57,36 @@ const JOIN_SUCCESS = 8 */ const INIT_CHANNEL_PONG = 10 + +class WebChannelGate { + constructor (action) { + this.door = null + this.accessData = null + this.action = action + } + + getAccessData () { + return this.accessData + } + + isOpen () { + return this.door !== null + } + + setOpen (door, accessData, action) { + this.door = door + this.door.onclose = this.action + this.accessData = accessData + } + + close () { + if (this.isOpen()) { + this.door.close() + this.door = null + } + } +} + /** * This class is an API starting point. It represents a group of collaborators * also called peers. Each peer can send/receive broadcast as well as personal @@ -129,8 +159,11 @@ class WebChannel { this.myId = this.generateId() this.onJoining = (id) => {} - this.onMessage = (id, msg) => {} + this.onMessage = (id, msg, isBroadcast) => {} this.onLeaving = (id) => {} + this.onClose = (closeEvt) => {} + + this.gate = new WebChannelGate((closeEvt) => this.onClose(closeEvt)) } /** Leave `WebChannel`. No longer can receive and send messages to the group. */ @@ -142,6 +175,7 @@ class WebChannel { c.close() }) this.channels.clear() + this.gate.close() } } @@ -206,8 +240,9 @@ class WebChannel { }) }) }).then((data) => { - this.webRTCOpen = data.socket - return {key: data.key, url: data.url} + let accessData = {key: data.key, url: data.url} + this.gate.setOpen(data.socket, accessData) + return accessData }) } @@ -215,9 +250,15 @@ class WebChannel { * Prevent other peers to join the `WebChannel` even if they have a key. */ closeForJoining () { - if (Reflect.has(this, 'webRTCOpen')) { - this.webRTCOpen.close() - } + this.gate.close() + } + + isOpen () { + return this.gate.isOpen() + } + + getAccess () { + return this.gate.getAccessData() } /** @@ -240,14 +281,6 @@ class WebChannel { }) } - /** - * - * - * @private - * @return {type} description - */ - isInviting () {} - /** * has - description * @@ -536,4 +569,5 @@ class WebChannel { return id } } + export {WebChannel, USER_DATA} diff --git a/test/functional/fullyConnected/2peers.test.js b/test/functional/fullyConnected/2peers.test.js index 4ebe473e..929e3584 100644 --- a/test/functional/fullyConnected/2peers.test.js +++ b/test/functional/fullyConnected/2peers.test.js @@ -9,8 +9,6 @@ describe('2 peers -> ', () => { expect(wc1.channels.size).toBe(wc2.channels.size) expect(wc1.channels.values().next().value.peerId).toBe(wc2.myId) expect(wc2.channels.values().next().value.peerId).toBe(wc1.myId) - // expect(wc1.joiningPeers.size).toBe(0) - // expect(wc2.joiningPeers.size).toBe(0) done() } wc1.openForJoining() @@ -24,11 +22,13 @@ describe('2 peers -> ', () => { describe('Should send/receive broadcast/personal messages -> ', () => { let wc1, wc2 + let access beforeAll((done) => { // Peer #1 wc1 = new WebChannel({signaling}) wc1.openForJoining().then((data) => { + access = data // Peer #2 wc2 = new WebChannel({signaling}) wc2.join(data.key).then(() => { @@ -38,6 +38,11 @@ describe('2 peers -> ', () => { }).catch(done.fail) }) + it('isOpen', () => { + expect(wc1.isOpen()).toBeTruthy() + expect(wc2.isOpen()).toBeFalsy() + }) + it('broadcast', (done) => { const message1 = 'Hi world!' const message2 = 'Hello world!' @@ -75,6 +80,38 @@ describe('2 peers -> ', () => { }) }) + it('Should get WebChannel access data after open', (done) => { + let wc1 = new WebChannel({signaling}) + wc1.openForJoining().then((data) => { + expect(wc1.getAccess()).toBe(data) + done() + }).catch(done.fail) + }) + + it('Should catch onClose WebChannel event', (done) => { + let wc1 = new WebChannel({signaling}) + wc1.onClose = (evt) => { + expect(evt instanceof Event).toBeTruthy() + done() + } + wc1.openForJoining().then((data) => { + wc1.closeForJoining() + }).catch(done.fail) + }) + + it('Should not enable to join the WebChannel after it has been closed', (done) => { + let wc1 = new WebChannel({signaling}) + let wc2 = new WebChannel({signaling}) + + // Peer #1 + wc1.openForJoining().then((data) => { + wc1.closeForJoining() + // Peer #2 + wc2.join(data.key).then(done.fail) + .catch(done) + }).catch(done.fail) + }) + describe('Should leave WebChannel -> ', () => { it('initiator is leaving', (done) => { const message = 'Hi world!'