|
|
|
|
@ -109,6 +109,7 @@ WS_PING_INTERVAL = 30000
|
|
|
|
|
|
|
|
|
|
class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):
|
|
|
|
|
ping_callback = None
|
|
|
|
|
last_ping = 0
|
|
|
|
|
last_pong = 0
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@ -151,7 +152,8 @@ class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):
|
|
|
|
|
|
|
|
|
|
# start the pinging
|
|
|
|
|
if self.ping_interval > 0:
|
|
|
|
|
self.last_pong = ioloop.IOLoop.instance().time()
|
|
|
|
|
self.last_ping = ioloop.IOLoop.instance().time() # Remember time of last ping
|
|
|
|
|
self.last_pong = self.last_ping
|
|
|
|
|
self.ping_callback = ioloop.PeriodicCallback(self.send_ping, self.ping_interval)
|
|
|
|
|
self.ping_callback.start()
|
|
|
|
|
|
|
|
|
|
@ -161,15 +163,19 @@ class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):
|
|
|
|
|
self.ping_callback.stop()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# check for timeout on pong
|
|
|
|
|
since_last_pong = 1e3 * (ioloop.IOLoop.instance().time() - self.last_pong)
|
|
|
|
|
if since_last_pong > self.ping_timeout:
|
|
|
|
|
# check for timeout on pong. Make sure that we really have sent a recent ping in
|
|
|
|
|
# case the machine with both server and client has been suspended since the last ping.
|
|
|
|
|
now = ioloop.IOLoop.instance().time()
|
|
|
|
|
since_last_pong = 1e3 * (now - self.last_pong)
|
|
|
|
|
since_last_ping = 1e3 * (now - self.last_ping)
|
|
|
|
|
if since_last_ping < 2*self.ping_interval and since_last_pong > self.ping_timeout:
|
|
|
|
|
self.log.warn("WebSocket ping timeout after %i ms.", since_last_pong)
|
|
|
|
|
self.close()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.ping(b'')
|
|
|
|
|
|
|
|
|
|
self.last_ping = now
|
|
|
|
|
|
|
|
|
|
def on_pong(self, data):
|
|
|
|
|
self.last_pong = ioloop.IOLoop.instance().time()
|
|
|
|
|
|
|
|
|
|
|