Implement connection force-close via ping timeout

Logging will show WSDISCONNECT.
This commit is contained in:
globophobe 2016-08-04 20:26:57 +09:00
parent dd3bf9b0b0
commit 9a2748d7da
4 changed files with 13 additions and 2 deletions

View File

@ -73,6 +73,12 @@ class CommandLineInterface(object):
help='The number of seconds a WebSocket must be idle before a keepalive ping is sent',
default=20,
)
self.parser.add_argument(
'--ping-timeout',
type=int,
help='The number of seconds before a WeSocket is closed if no response to a keepalive ping',
default=30,
)
self.parser.add_argument(
'channel_layer',
help='The ASGI channel layer instance to use as path.to.module:instance.path',
@ -143,6 +149,7 @@ class CommandLineInterface(object):
file_descriptor=args.file_descriptor,
http_timeout=args.http_timeout,
ping_interval=args.ping_interval,
ping_timeout=args.ping_timeout,
action_logger=AccessLogGenerator(access_log_stream) if access_log_stream else None,
ws_protocols=args.ws_protocols,
root_path=args.root_path,

View File

@ -276,7 +276,7 @@ class HTTPFactory(http.HTTPFactory):
protocol = HTTPProtocol
def __init__(self, channel_layer, action_logger=None, timeout=120, websocket_timeout=86400, ping_interval=20, ws_protocols=None, root_path=""):
def __init__(self, channel_layer, action_logger=None, timeout=120, websocket_timeout=86400, ping_interval=20, ping_timeout=30, ws_protocols=None, root_path=""):
http.HTTPFactory.__init__(self)
self.channel_layer = channel_layer
self.action_logger = action_logger
@ -287,6 +287,7 @@ class HTTPFactory(http.HTTPFactory):
self.reply_protocols = {}
# Make a factory for WebSocket protocols
self.ws_factory = WebSocketFactory(self, protocols=ws_protocols)
self.ws_factory.setProtocolOptions(autoPingTimeout=ping_timeout)
self.ws_factory.protocol = WebSocketProtocol
self.ws_factory.reply_protocols = self.reply_protocols
self.root_path = root_path

View File

@ -23,6 +23,7 @@ class Server(object):
http_timeout=120,
websocket_timeout=None,
ping_interval=20,
ping_timeout=30,
ws_protocols=None,
root_path="",
):
@ -35,6 +36,7 @@ class Server(object):
self.action_logger = action_logger
self.http_timeout = http_timeout
self.ping_interval = ping_interval
self.ping_timeout = ping_timeout
# If they did not provide a websocket timeout, default it to the
# channel layer's group_expiry value if present, or one day if not.
self.websocket_timeout = websocket_timeout or getattr(channel_layer, "group_expiry", 86400)
@ -48,6 +50,7 @@ class Server(object):
timeout=self.http_timeout,
websocket_timeout=self.websocket_timeout,
ping_interval=self.ping_interval,
ping_timeout=self.ping_timeout,
ws_protocols=self.ws_protocols,
root_path=self.root_path,
)

View File

@ -189,7 +189,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
Checks to see if we should send a keepalive ping.
"""
if (time.time() - self.last_data) > self.main_factory.ping_interval:
self.sendPing()
self._sendAutoPing()
self.last_data = time.time()