implemented timeout over websocket connection
This commit is contained in:
		
							parent
							
								
									76495e674d
								
							
						
					
					
						commit
						913f36043a
					
				| @ -51,6 +51,6 @@ | |||||||
|     "jsonwebtoken": "^7.1.9", |     "jsonwebtoken": "^7.1.9", | ||||||
|     "sni": "^1.0.0", |     "sni": "^1.0.0", | ||||||
|     "tunnel-packer": "^1.1.0", |     "tunnel-packer": "^1.1.0", | ||||||
|     "ws": "^1.1.1" |     "ws": "^2.2.3" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										66
									
								
								wsclient.js
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								wsclient.js
									
									
									
									
									
								
							| @ -7,6 +7,9 @@ var Packer = require('tunnel-packer'); | |||||||
| 
 | 
 | ||||||
| function run(copts) { | function run(copts) { | ||||||
|   var tunnelUrl = copts.stunneld.replace(/\/$/, '') + '/?access_token=' + copts.token; |   var tunnelUrl = copts.stunneld.replace(/\/$/, '') + '/?access_token=' + copts.token; | ||||||
|  |   var activityTimeout = copts.activityTimeout || 2*60*1000; | ||||||
|  |   var pongTimeout = copts.pongTimeout || 10*1000; | ||||||
|  | 
 | ||||||
|   var wstunneler; |   var wstunneler; | ||||||
|   var authenticated = false; |   var authenticated = false; | ||||||
| 
 | 
 | ||||||
| @ -164,23 +167,65 @@ function run(copts) { | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   var retry = true; |   var retry = true; | ||||||
|   var retryTimeout; |   var lastActivity; | ||||||
|  |   var timeoutId; | ||||||
|   var wsHandlers = { |   var wsHandlers = { | ||||||
|     onOpen: function () { |     refreshTimeout: function () { | ||||||
|  |       lastActivity = Date.now(); | ||||||
|  |     } | ||||||
|  |   , checkTimeout: function () { | ||||||
|  |       if (!wstunneler) { | ||||||
|  |         console.warn('checkTimeout called when websocket already closed'); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       // Determine how long the connection has been "silent", ie no activity.
 | ||||||
|  |       var silent = Date.now() - lastActivity; | ||||||
|  | 
 | ||||||
|  |       // If we have had activity within the last activityTimeout then all we need to do is
 | ||||||
|  |       // call this function again at the soonest time when the connection could be timed out.
 | ||||||
|  |       if (silent < activityTimeout) { | ||||||
|  |         timeoutId = setTimeout(wsHandlers.checkTimeout, activityTimeout-silent); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Otherwise we check to see if the pong has also timed out, and if not we send a ping
 | ||||||
|  |       // and call this function again when the pong will have timed out.
 | ||||||
|  |       else if (silent < activityTimeout + pongTimeout) { | ||||||
|  |         console.log('pinging tunnel server'); | ||||||
|  |         try { | ||||||
|  |           wstunneler.ping(); | ||||||
|  |         } catch (err) { | ||||||
|  |           console.warn('failed to ping tunnel server', err); | ||||||
|  |         } | ||||||
|  |         timeoutId = setTimeout(wsHandlers.checkTimeout, pongTimeout); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Last case means the ping we sent before didn't get a response soon enough, so we
 | ||||||
|  |       // need to close the websocket connection.
 | ||||||
|  |       else { | ||||||
|  |         console.log('connection timed out'); | ||||||
|  |         wstunneler.close(1000, 'connection timeout'); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   , onOpen: function () { | ||||||
|       console.info("[open] connected to '" + copts.stunneld + "'"); |       console.info("[open] connected to '" + copts.stunneld + "'"); | ||||||
|  |       wsHandlers.refreshTimeout(); | ||||||
|  |       timeoutId = setTimeout(wsHandlers.checkTimeout, activityTimeout); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   , onClose: function () { |   , onClose: function () { | ||||||
|       console.log('ON CLOSE'); |       console.log('ON CLOSE'); | ||||||
|  |       clearTimeout(timeoutId); | ||||||
|       wstunneler = null; |       wstunneler = null; | ||||||
|       clientHandlers.closeAll(); |       clientHandlers.closeAll(); | ||||||
| 
 | 
 | ||||||
|       if (!authenticated) { |       if (!authenticated) { | ||||||
|         console.info('[close] failed on first attempt... check authentication.'); |         console.info('[close] failed on first attempt... check authentication.'); | ||||||
|  |         timeoutId = null; | ||||||
|       } |       } | ||||||
|       else if (retry) { |       else if (retry) { | ||||||
|         console.info('[retry] disconnected and waiting...'); |         console.info('[retry] disconnected and waiting...'); | ||||||
|         retryTimeout = setTimeout(connect, 5000); |         timeoutId = setTimeout(connect, 5000); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -192,7 +237,7 @@ function run(copts) { | |||||||
|   , sendMessage: function (msg) { |   , sendMessage: function (msg) { | ||||||
|       if (wstunneler) { |       if (wstunneler) { | ||||||
|         try { |         try { | ||||||
|           wstunneler.send(msg, {binary: true}) |           wstunneler.send(msg, {binary: true}); | ||||||
|         } catch (err) { |         } catch (err) { | ||||||
|           console.warn('[sendMessage] error sending websocket message', err); |           console.warn('[sendMessage] error sending websocket message', err); | ||||||
|         } |         } | ||||||
| @ -204,7 +249,7 @@ function run(copts) { | |||||||
|     if (!retry) { |     if (!retry) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     retryTimeout = null; |     timeoutId = null; | ||||||
|     var machine = require('tunnel-packer').create(packerHandlers); |     var machine = require('tunnel-packer').create(packerHandlers); | ||||||
| 
 | 
 | ||||||
|     console.info("[connect] '" + copts.stunneld + "'"); |     console.info("[connect] '" + copts.stunneld + "'"); | ||||||
| @ -212,7 +257,12 @@ function run(copts) { | |||||||
|     wstunneler.on('open', wsHandlers.onOpen); |     wstunneler.on('open', wsHandlers.onOpen); | ||||||
|     wstunneler.on('close', wsHandlers.onClose); |     wstunneler.on('close', wsHandlers.onClose); | ||||||
|     wstunneler.on('error', wsHandlers.onError); |     wstunneler.on('error', wsHandlers.onError); | ||||||
|  | 
 | ||||||
|  |     // Our library will automatically handle sending the pong respose to ping requests.
 | ||||||
|  |     wstunneler.on('ping', wsHandlers.refreshTimeout); | ||||||
|  |     wstunneler.on('pong', wsHandlers.refreshTimeout); | ||||||
|     wstunneler.on('message', function (data, flags) { |     wstunneler.on('message', function (data, flags) { | ||||||
|  |       wsHandlers.refreshTimeout(); | ||||||
|       if (data.error || '{' === data[0]) { |       if (data.error || '{' === data[0]) { | ||||||
|         console.log(data); |         console.log(data); | ||||||
|         return; |         return; | ||||||
| @ -231,9 +281,9 @@ function run(copts) { | |||||||
|     process.removeListener('SIGINT', sigHandler); |     process.removeListener('SIGINT', sigHandler); | ||||||
| 
 | 
 | ||||||
|     retry = false; |     retry = false; | ||||||
|     if (retryTimeout) { |     if (timeoutId) { | ||||||
|       clearTimeout(retryTimeout); |       clearTimeout(timeoutId); | ||||||
|       retryTimeout = null; |       timeoutId = null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (wstunneler) { |     if (wstunneler) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user