From b5210e38c43bd81be317493760ca9c68c3ef1cd7 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Mon, 13 Jul 2015 19:15:44 -0700 Subject: [PATCH] Keepalive messages for WebSockets, and ! response chan prefix --- channels/interfaces/websocket_twisted.py | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/channels/interfaces/websocket_twisted.py b/channels/interfaces/websocket_twisted.py index 5e3dbe1..824a0cf 100644 --- a/channels/interfaces/websocket_twisted.py +++ b/channels/interfaces/websocket_twisted.py @@ -1,9 +1,11 @@ import django import time + +from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory from collections import deque from twisted.internet import reactor + from channels import Channel, channel_backends, DEFAULT_CHANNEL_BACKEND -from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory class InterfaceProtocol(WebSocketServerProtocol): @@ -20,7 +22,8 @@ class InterfaceProtocol(WebSocketServerProtocol): def onOpen(self): # Make sending channel - self.send_channel = Channel.new_name("django.websocket.send") + self.send_channel = Channel.new_name("!django.websocket.send") + self.last_keepalive = time.time() self.factory.protocols[self.send_channel] = self # Send news that this channel is open Channel("django.websocket.connect").send( @@ -67,6 +70,16 @@ class InterfaceProtocol(WebSocketServerProtocol): **self.request_info ) + def sendKeepalive(self): + """ + Sends a keepalive packet on the keepalive channel. + """ + Channel("django.websocket.keepalive").send( + send_channel = self.send_channel, + **self.request_info + ) + self.last_keepalive = time.time() + class InterfaceFactory(WebSocketServerFactory): """ @@ -106,6 +119,7 @@ class WebsocketTwistedInterface(object): self.factory.protocol = InterfaceProtocol reactor.listenTCP(self.port, self.factory) reactor.callInThread(self.backend_reader) + reactor.callLater(1, self.keepalive_sender) reactor.run() def backend_reader(self): @@ -130,3 +144,14 @@ class WebsocketTwistedInterface(object): continue # Deal with the message self.factory.dispatch_send(channel, message) + + def keepalive_sender(self): + """ + Sends keepalive messages for open WebSockets every + (channel_backend expiry / 2) seconds. + """ + expiry_window = int(self.channel_backend.expiry / 2) + for protocol in self.factory.protocols.values(): + if time.time() - protocol.last_keepalive > expiry_window: + protocol.sendKeepalive() + reactor.callLater(1, self.keepalive_sender)