diff --git a/app/authenticated/route.js b/app/authenticated/route.js index 9a4f85d80..3d19f94eb 100644 --- a/app/authenticated/route.js +++ b/app/authenticated/route.js @@ -7,6 +7,7 @@ import C from 'ui/utils/constants'; export default Ember.Route.extend(AuthenticatedRouteMixin, { socket: null, + pingTimer: null, model: function(params, transition) { var store = this.get('store'); @@ -220,13 +221,13 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { }, // Raw message from the WebSocket - //wsMessage: function(/*data*/) { - //console.log('wsMessage',data); + //subscribeMessage: function(/*data*/) { + //console.log('subscribeMessage',data); //}, // WebSocket connected - wsConnected: function(tries,msec) { - var msg = 'WebSocket connected'; + subscribeConnected: function(tries,msec) { + var msg = 'Subscribe connected'; if (tries > 0) { msg += ' (after '+ tries + ' ' + (tries === 1 ? 'try' : 'tries'); @@ -241,37 +242,21 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { }, // WebSocket disconnected - wsDisconnected: function() { - console.log('WebSocket disconnected'); + subscribeDisconnected: function() { + console.log('Subscribe disconnected'); }, - wsPing: function() { - console.log('WebSocket ping'); - }, - - /* - agentChanged: function(change) { - if (!change || !change.data || !change.data.resource) + subscribePing: function() { + console.log('Subscribe ping'); + if ( this.get('pingTimer') ) { - return; + Ember.run.cancel(this.get('pingTimer')); } - //console.log('Agent Changed:', change); - var agent = change.data.resource; - var id = agent.id; - delete agent.hosts; - var hosts = this.controllerFor('hosts'); - hosts.forEach(function(host) { - if ( host.get('agent.id') === id ) - { - host.get('agent').setProperties(agent); - } - }); - }, - */ - - machineChanged: function(change) { - console.log('Machine changed:',change); + this.set('pingTimer', Ember.run.later(this, function() { + console.log('Subscribe missed 2 pings...'); + this.get('socket').connect(); + }, 11000)); }, hostChanged: function(change) { @@ -282,7 +267,6 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { { machine.get('hosts').addObject(host); } - console.log('Host changed:',change); }, containerChanged: function(change) { @@ -395,7 +379,7 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { socket.on('message', (event) => { var d = JSON.parse(event.data, boundTypeify); - //this._trySend('wsMessage',d); + //this._trySend('subscribeMessage',d); var str = d.name; if ( d.resourceType ) @@ -415,7 +399,7 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { } else if ( d.name === 'ping' ) { - action = 'wsPing'; + action = 'subscribePing'; } if ( action ) @@ -425,11 +409,11 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { }); socket.on('connected', (tries, after) => { - this._trySend('wsConnected', tries, after); + this._trySend('subscribeConnected', tries, after); }); socket.on('disconnected', () => { - this._trySend('wsDisconnected', this.get('tries')); + this._trySend('subscribeDisconnected', this.get('tries')); }); this.set('socket', socket); diff --git a/app/utils/socket.js b/app/utils/socket.js index 9c096cb02..b7af39adb 100644 --- a/app/utils/socket.js +++ b/app/utils/socket.js @@ -1,5 +1,9 @@ import Ember from "ember"; +var INSECURE = 'ws://'; +var SECURE = 'wss://'; +var sockId = 1; + export default Ember.Object.extend(Ember.Evented, { url: null, socket: null, @@ -10,8 +14,7 @@ export default Ember.Object.extend(Ember.Evented, { disconnectCb: null, connect: function() { - var self = this; - var socket = self.get('socket'); + var socket = this.get('socket'); if ( socket ) { this.disconnect(); @@ -19,71 +22,27 @@ export default Ember.Object.extend(Ember.Evented, { var url = this.get('url'); // If the site is SSL, the WebSocket should be too... - if ( window.location.protocol === 'https:' && url.indexOf('ws://') === 0 ) + if ( window.location.protocol === 'https:' && url.indexOf(INSECURE) === 0 ) { - url = 'wss://' + url.substr(5); + url = SECURE + url.substr(INSECURE.length); } - console.log('Socket connect to',url); + var id = sockId++; + console.log('Socket connect',id,'to', url.replace(/\?.*/,'')+'...'); + socket = new WebSocket(url); - self.set('socket', socket); + socket.__sockId = id; + this.set('socket', socket); - socket.onmessage = function(event) { - Ember.run(function() { - self.trigger('message',event); - }); - }; - - socket.onopen = function() { - //console.log('Socket Open'); - var now = (new Date()).getTime(); - self.set('connected',true); - - var at = self.get('disconnectedAt'); - var after = null; - if ( at ) - { - after = now - at; - } - - self.trigger('connected', self.get('tries'), after); - self.set('tries',0); - self.set('disconnectedAt', null); - }; - - socket.onclose = function() { - //console.log('Socket Closed'); - var wasConnected = self.get('connected'); - - self.set('connected',false); - self.incrementProperty('tries'); - - if ( self.get('disconnectedAt') === null ) - { - self.set('disconnectedAt', (new Date()).getTime()); - } - - socket.close(); - if ( wasConnected && self.get('autoReconnect') ) - { - var delay = Math.max(1000, Math.min(1000 * self.get('tries'), 30000)); - setTimeout(self.connect.bind(self), delay); - } - - if ( self.get('disconnectCb') ) - { - self.get('disconnectCb')(); - } - else - { - self.trigger('disconnected', self.get('tries')); - } - }; + socket.onmessage = Ember.run.bind(this, this._message); + socket.onopen = Ember.run.bind(this, this._opened); + socket.onerror = Ember.run.bind(this, this._error); + socket.onclose = Ember.run.bind(this, this._closed); }, disconnect: function(cb) { - var self = this; - //console.log('Socket disconnect'); + this._log('disconnect'); + if ( !this.get('connected') ) { if ( cb ) @@ -93,24 +52,95 @@ export default Ember.Object.extend(Ember.Evented, { return; } - this.set('connected', false); - this.set('autoReconnect',false); - if ( typeof cb === 'function' ) - { - this.set('disconnectCb', cb); - } + this.setProperties({ + 'autoReconnect': false, + 'disconnectCb': cb + }); var socket = this.get('socket'); if ( socket ) { try { + this._log('closing'); + socket.onopen = null; + socket.onerror = null; + socket.onmessage = null; socket.close(); - self.set('socket',null); + this.set('socket',null); } catch (e) { + this._log('exception', e); // Meh.. } } - } + }, + + _opened: function() { + this._log('opened'); + var now = (new Date()).getTime(); + + var at = this.get('disconnectedAt'); + var after = null; + if ( at ) + { + after = now - at; + } + + this.setProperties({ + connected: true, + tries: 0, + disconnectedAt: null, + }); + + this.trigger('connected', this.get('tries'), after); + }, + + _message: function(event) { + this.trigger('message',event); + }, + + _error: function() { + this._log('error'); + this.disconnect(); + }, + + _closed: function() { + console.log('Socket closed'); + + var wasConnected = this.get('connected'); + this.set('connected',false); + this.incrementProperty('tries'); + + if ( this.get('disconnectedAt') === null ) + { + this.set('disconnectedAt', (new Date()).getTime()); + } + + if ( wasConnected && this.get('autoReconnect') ) + { + var delay = Math.max(1000, Math.min(1000 * this.get('tries'), 30000)); + Ember.run.later(this, this.connect, delay); + } + + if ( typeof this.get('disconnectCb') === 'function' ) + { + this.get('disconnectCb')(); + } + + if ( wasConnected ) + { + this.trigger('disconnected'); + } + }, + + _log: function(/*arguments*/) { + var args = ['Socket', this.get('socket.__sockId') ]; + for ( var i = 0 ; i < arguments.length ; i++ ) + { + args.push(arguments[i]); + } + + console.log.apply(console, args); + }, }); diff --git a/server/proxies/api.js b/server/proxies/api.js index 17fe9b2b7..e0b5d644a 100644 --- a/server/proxies/api.js +++ b/server/proxies/api.js @@ -75,7 +75,11 @@ module.exports = function(app, options) { detail: err.toString() } - if ( !req.upgrade ) + if ( req.upgrade ) + { + res.end(); + } + else { res.writeHead(500, {'Content-Type': 'application/json'}); res.end(JSON.stringify(error));