@@ -4654,6 +4654,8 @@ exports.TOPIC.PRIVATE = 'PRIVATE/';
46544654exports . EVENT = { } ;
46554655exports . EVENT . CONNECTION_ERROR = 'connectionError' ;
46564656exports . EVENT . CONNECTION_STATE_CHANGED = 'connectionStateChanged' ;
4657+ exports . EVENT . MAX_RECONNECTION_ATTEMPTS_REACHED = 'MAX_RECONNECTION_ATTEMPTS_REACHED' ;
4658+ exports . EVENT . CONNECTION_AUTHENTICATION_TIMEOUT = 'CONNECTION_AUTHENTICATION_TIMEOUT' ;
46574659exports . EVENT . ACK_TIMEOUT = 'ACK_TIMEOUT' ;
46584660exports . EVENT . NO_RPC_PROVIDER = 'NO_RPC_PROVIDER' ;
46594661exports . EVENT . RESPONSE_TIMEOUT = 'RESPONSE_TIMEOUT' ;
@@ -4763,6 +4765,13 @@ module.exports = {
47634765 */
47644766 reconnectIntervalIncrement : 4000 ,
47654767
4768+ /**
4769+ * @param {Number } maxReconnectInterval Specifies the maximum number of milliseconds for the reconnectIntervalIncrement
4770+ * The amount of reconnections will reach this value
4771+ * then reconnectIntervalIncrement will be ignored.
4772+ */
4773+ maxReconnectInterval : 180000 ,
4774+
47664775 /**
47674776 * @param {Number } maxReconnectAttempts The number of reconnection attempts until the client gives
47684777 * up and declares the connection closed
@@ -5133,6 +5142,7 @@ var Connection = function( client, url, options ) {
51335142 this . _deliberateClose = false ;
51345143 this . _redirecting = false ;
51355144 this . _tooManyAuthAttempts = false ;
5145+ this . _connectionAuthenticationTimeout = false ;
51365146 this . _challengeDenied = false ;
51375147 this . _queuedMessages = [ ] ;
51385148 this . _reconnectTimeout = null ;
@@ -5148,7 +5158,7 @@ var Connection = function( client, url, options ) {
51485158
51495159/**
51505160 * Returns the current connection state.
5151- * (One of constants.CONNECTION_STATE)
5161+ * (One of constants.CONNECTION_STATE)
51525162 *
51535163 * @public
51545164 * @returns {String } connectionState
@@ -5172,7 +5182,7 @@ Connection.prototype.authenticate = function( authParams, callback ) {
51725182 this . _authParams = authParams ;
51735183 this . _authCallback = callback ;
51745184
5175- if ( this . _tooManyAuthAttempts || this . _challengeDenied ) {
5185+ if ( this . _tooManyAuthAttempts || this . _challengeDenied || this . _connectionAuthenticationTimeout ) {
51765186 this . _client . _$onError ( C . TOPIC . ERROR , C . EVENT . IS_CLOSED , 'this client\'s connection was closed' ) ;
51775187 return ;
51785188 }
@@ -5181,7 +5191,7 @@ Connection.prototype.authenticate = function( authParams, callback ) {
51815191 this . _deliberateClose = false ;
51825192 return ;
51835193 }
5184-
5194+
51855195 if ( this . _state === C . CONNECTION_STATE . AWAITING_AUTHENTICATION ) {
51865196 this . _sendAuthParams ( ) ;
51875197 }
@@ -5221,7 +5231,7 @@ Connection.prototype.send = function( message ) {
52215231 this . _currentMessageResetTimeout = utils . nextTick ( this . _resetCurrentMessageCount . bind ( this ) ) ;
52225232 }
52235233
5224- if ( this . _state === C . CONNECTION_STATE . OPEN &&
5234+ if ( this . _state === C . CONNECTION_STATE . OPEN &&
52255235 this . _queuedMessages . length < this . _options . maxMessagesPerPacket &&
52265236 this . _currentPacketMessageCount < this . _options . maxMessagesPerPacket ) {
52275237 this . _sendQueuedMessages ( ) ;
@@ -5341,7 +5351,7 @@ Connection.prototype._sendAuthParams = function() {
53415351
53425352/**
53435353 * Will be invoked once the connection is established. The client
5344- * can't send messages yet, and needs to get a connection ACK or REDIRECT
5354+ * can't send messages yet, and needs to get a connection ACK or REDIRECT
53455355 * from the server before authenticating
53465356 *
53475357 * @private
@@ -5394,7 +5404,7 @@ Connection.prototype._onClose = function() {
53945404 }
53955405 else if ( this . _deliberateClose === true ) {
53965406 this . _setState ( C . CONNECTION_STATE . CLOSED ) ;
5397- }
5407+ }
53985408 else {
53995409 if ( this . _originalUrl !== this . _url ) {
54005410 this . _url = this . _originalUrl ;
@@ -5442,7 +5452,7 @@ Connection.prototype._onMessage = function( message ) {
54425452 * by the client until the authentication is successful.
54435453 *
54445454 * If a challenge is recieved, the user will send the url to the server
5445- * in response to get the appropriate redirect. If the URL is invalid the
5455+ * in response to get the appropriate redirect. If the URL is invalid the
54465456 * server will respond with a REJECTION resulting in the client connection
54475457 * being permanently closed.
54485458 *
@@ -5457,15 +5467,15 @@ Connection.prototype._onMessage = function( message ) {
54575467Connection . prototype . _handleConnectionResponse = function ( message ) {
54585468 var data ;
54595469
5460- if ( message . action === C . ACTIONS . ACK ) {
5470+ if ( message . action === C . ACTIONS . ACK ) {
54615471 this . _setState ( C . CONNECTION_STATE . AWAITING_AUTHENTICATION ) ;
54625472 if ( this . _authParams ) {
54635473 this . _sendAuthParams ( ) ;
54645474 }
5465- }
5475+ }
54665476 else if ( message . action === C . ACTIONS . CHALLENGE ) {
54675477 this . _setState ( C . CONNECTION_STATE . CHALLENGING ) ;
5468- this . _endpoint . send ( messageBuilder . getMsg ( C . TOPIC . CONNECTION , C . ACTIONS . CHALLENGE_RESPONSE , [ this . _originalUrl ] ) ) ;
5478+ this . _endpoint . send ( messageBuilder . getMsg ( C . TOPIC . CONNECTION , C . ACTIONS . CHALLENGE_RESPONSE , [ this . _originalUrl ] ) ) ;
54695479 }
54705480 else if ( message . action === C . ACTIONS . REJECTION ) {
54715481 this . _challengeDenied = true ;
@@ -5476,6 +5486,13 @@ Connection.prototype._handleConnectionResponse = function( message ) {
54765486 this . _redirecting = true ;
54775487 this . _endpoint . close ( ) ;
54785488 }
5489+ else if ( message . action === C . ACTIONS . ERROR ) {
5490+ if ( message . data [ 0 ] === C . EVENT . CONNECTION_AUTHENTICATION_TIMEOUT ) {
5491+ this . _deliberateClose = true ;
5492+ this . _connectionAuthenticationTimeout = true ;
5493+ this . _client . _$onError ( C . TOPIC . CONNECTION , message . data [ 0 ] , message . data [ 1 ] ) ;
5494+ }
5495+ }
54795496} ;
54805497
54815498/**
@@ -5493,21 +5510,21 @@ Connection.prototype._handleAuthResponse = function( message ) {
54935510 var data ;
54945511
54955512 if ( message . action === C . ACTIONS . ERROR ) {
5496-
5513+
54975514 if ( message . data [ 0 ] === C . EVENT . TOO_MANY_AUTH_ATTEMPTS ) {
54985515 this . _deliberateClose = true ;
54995516 this . _tooManyAuthAttempts = true ;
55005517 } else {
55015518 this . _setState ( C . CONNECTION_STATE . AWAITING_AUTHENTICATION ) ;
55025519 }
5503-
5520+
55045521 if ( this . _authCallback ) {
55055522 this . _authCallback ( false , this . _getAuthData ( message . data [ 1 ] ) ) ;
55065523 }
5507-
5524+
55085525 } else if ( message . action === C . ACTIONS . ACK ) {
55095526 this . _setState ( C . CONNECTION_STATE . OPEN ) ;
5510-
5527+
55115528 if ( this . _authCallback ) {
55125529 this . _authCallback ( true , this . _getAuthData ( message . data [ 0 ] ) ) ;
55135530 }
@@ -5534,7 +5551,7 @@ Connection.prototype._getAuthData = function( data ) {
55345551} ;
55355552
55365553/**
5537- * Updates the connection state and emits the
5554+ * Updates the connection state and emits the
55385555 * connectionStateChanged event on the client
55395556 *
55405557 * @private
@@ -5551,7 +5568,7 @@ Connection.prototype._setState = function( state ) {
55515568 *
55525569 * If the number of failed reconnection attempts exceeds
55535570 * options.maxReconnectAttempts the connection is closed
5554- *
5571+ *
55555572 * @private
55565573 * @returns {void }
55575574 */
@@ -5564,18 +5581,22 @@ Connection.prototype._tryReconnect = function() {
55645581 this . _setState ( C . CONNECTION_STATE . RECONNECTING ) ;
55655582 this . _reconnectTimeout = setTimeout (
55665583 this . _tryOpen . bind ( this ) ,
5567- this . _options . reconnectIntervalIncrement * this . _reconnectionAttempt
5584+ Math . min (
5585+ this . _options . maxReconnectInterval ,
5586+ this . _options . reconnectIntervalIncrement * this . _reconnectionAttempt
5587+ )
55685588 ) ;
55695589 this . _reconnectionAttempt ++ ;
55705590 } else {
55715591 this . _clearReconnect ( ) ;
55725592 this . close ( ) ;
5593+ this . _client . emit ( C . MAX_RECONNECTION_ATTEMPTS_REACHED , this . _reconnectionAttempt ) ;
55735594 }
55745595} ;
55755596
55765597/**
55775598 * Attempts to open a errourosly closed connection
5578- *
5599+ *
55795600 * @private
55805601 * @returns {void }
55815602 */
@@ -5600,6 +5621,7 @@ Connection.prototype._clearReconnect = function() {
56005621} ;
56015622
56025623module . exports = Connection ;
5624+
56035625} , { "../constants/constants" :35 , "../tcp/tcp-connection" :31 , "../utils/utils" :54 , "./message-builder" :40 , "./message-parser" :41 , "engine.io-client" :2 } ] , 40 :[ function ( _dereq_ , module , exports ) {
56045626var C = _dereq_ ( '../constants/constants' ) ,
56055627 SEP = C . MESSAGE_PART_SEPERATOR ;
@@ -6287,10 +6309,22 @@ List.prototype.subscribe = function() {
62876309 }
62886310
62896311 //Make sure the callback is invoked with an empty array for new records
6290- parameters . callback = function ( callback ) {
6312+ var listCallback = function ( callback ) {
62916313 callback ( this . getEntries ( ) ) ;
62926314 } . bind ( this , parameters . callback ) ;
62936315
6316+ /**
6317+ * Adding a property onto a function directly is terrible practice,
6318+ * and we will change this as soon as we have a more seperate approach
6319+ * of creating lists that doesn't have records default state.
6320+ *
6321+ * The reason we are holding a referencing to wrapped array is so that
6322+ * on unsubscribe it can provide a reference to the actual method the
6323+ * record is subscribed too.
6324+ **/
6325+ parameters . callback . wrappedCallback = listCallback ;
6326+ parameters . callback = listCallback ;
6327+
62946328 this . _record . subscribe ( parameters ) ;
62956329} ;
62966330
@@ -6308,6 +6342,7 @@ List.prototype.unsubscribe = function() {
63086342 throw new Error ( 'path is not supported for List.unsubscribe' ) ;
63096343 }
63106344
6345+ parameters . callback = parameters . callback . wrappedCallback ;
63116346 this . _record . unsubscribe ( parameters ) ;
63126347} ;
63136348
@@ -6389,7 +6424,7 @@ List.prototype._hasIndex = function( index ) {
63896424
63906425/**
63916426 * Establishes the current structure of the list, provided the client has attached any
6392- * add / move / remove listener
6427+ * add / move / remove listener
63936428 *
63946429 * This will be called before any change to the list, regardsless if the change was triggered
63956430 * by an incoming message from the server or by the client
@@ -6434,7 +6469,7 @@ List.prototype._afterChange = function() {
64346469 }
64356470 }
64366471 }
6437-
6472+
64386473 if ( this . _hasAddListener || this . _hasMoveListener ) {
64396474 for ( entry in after ) {
64406475 if ( before [ entry ] === undefined ) {
@@ -6463,7 +6498,7 @@ List.prototype._afterChange = function() {
64636498 * {
64646499 * 'recordA': [ 0, 3 ],
64656500 * 'recordB': [ 1 ],
6466- * 'recordC': [ 2 ]
6501+ * 'recordC': [ 2 ]
64676502 * }
64686503 *
64696504 * @private
@@ -6626,7 +6661,7 @@ RecordHandler.prototype.unlisten = function( pattern ) {
66266661 * @public
66276662 */
66286663RecordHandler . prototype . snapshot = function ( name , callback ) {
6629- if ( this . _records [ name ] ) {
6664+ if ( this . _records [ name ] && this . _records [ name ] . isReady ) {
66306665 callback ( null , this . _records [ name ] . get ( ) ) ;
66316666 } else {
66326667 this . _snapshotRegistry . request ( name , callback ) ;
@@ -6962,20 +6997,23 @@ Record.prototype.set = function( pathOrData, data ) {
69626997 * @returns {void }
69636998 */
69646999Record . prototype . subscribe = function ( path , callback , triggerNow ) {
6965- var i , args = this . _normalizeArguments ( arguments ) ;
7000+ var args = this . _normalizeArguments ( arguments ) ;
69667001
69677002 if ( this . _checkDestroyed ( 'subscribe' ) ) {
69687003 return ;
69697004 }
69707005
6971- this . _eventEmitter . on ( args . path || ALL_EVENT , args . callback ) ;
6972-
6973- if ( args . triggerNow && this . isReady ) {
6974- if ( args . path ) {
6975- args . callback ( this . _getPath ( args . path ) . getValue ( ) ) ;
6976- } else {
6977- args . callback ( this . _$data ) ;
6978- }
7006+ if ( args . triggerNow ) {
7007+ this . whenReady ( function ( ) {
7008+ this . _eventEmitter . on ( args . path || ALL_EVENT , args . callback ) ;
7009+ if ( args . path ) {
7010+ args . callback ( this . _getPath ( args . path ) . getValue ( ) ) ;
7011+ } else {
7012+ args . callback ( this . _$data ) ;
7013+ }
7014+ } . bind ( this ) ) ;
7015+ } else {
7016+ this . _eventEmitter . on ( args . path || ALL_EVENT , args . callback ) ;
69797017 }
69807018} ;
69817019
@@ -6997,11 +7035,16 @@ Record.prototype.subscribe = function( path, callback, triggerNow ) {
69977035 * @returns {void }
69987036 */
69997037Record . prototype . unsubscribe = function ( pathOrCallback , callback ) {
7038+ var args = this . _normalizeArguments ( arguments ) ;
7039+
70007040 if ( this . _checkDestroyed ( 'unsubscribe' ) ) {
70017041 return ;
70027042 }
7003- var event = arguments . length === 2 ? pathOrCallback : ALL_EVENT ;
7004- this . _eventEmitter . off ( event , callback ) ;
7043+ if ( args . path ) {
7044+ this . _eventEmitter . off ( args . path , args . callback ) ;
7045+ } else {
7046+ this . _eventEmitter . off ( ALL_EVENT , args . callback ) ;
7047+ }
70057048} ;
70067049
70077050/**
@@ -7012,15 +7055,14 @@ Record.prototype.unsubscribe = function( pathOrCallback, callback ) {
70127055 * @returns {void }
70137056 */
70147057Record . prototype . discard = function ( ) {
7015- this . usages -- ;
7016-
7017- if ( this . usages <= 0 ) {
7018- this . whenReady ( function ( ) {
7019- this . emit ( 'destroyPending' ) ;
7020- this . _discardTimeout = setTimeout ( this . _onTimeout . bind ( this , C . EVENT . ACK_TIMEOUT ) , this . _options . subscriptionTimeout ) ;
7021- this . _connection . sendMsg ( C . TOPIC . RECORD , C . ACTIONS . UNSUBSCRIBE , [ this . name ] ) ;
7022- } . bind ( this ) ) ;
7023- }
7058+ this . whenReady ( function ( ) {
7059+ this . usages -- ;
7060+ if ( this . usages <= 0 ) {
7061+ this . emit ( 'destroyPending' ) ;
7062+ this . _discardTimeout = setTimeout ( this . _onTimeout . bind ( this , C . EVENT . ACK_TIMEOUT ) , this . _options . subscriptionTimeout ) ;
7063+ this . _connection . sendMsg ( C . TOPIC . RECORD , C . ACTIONS . UNSUBSCRIBE , [ this . name ] ) ;
7064+ }
7065+ } . bind ( this ) ) ;
70247066} ;
70257067
70267068/**
0 commit comments