Skip to content

Commit

Permalink
server: close TCP connection after closing websocket (#150)
Browse files Browse the repository at this point in the history
Fixes #115 and #147.
  • Loading branch information
belm0 authored Feb 3, 2021
1 parent dbf819d commit 719c06a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ docs:
$(MAKE) -C docs html

test:
$(PYTHON) -m pytest --cov=trio_websocket
$(PYTHON) -m pytest --cov=trio_websocket --no-cov-on-fail

lint:
$(PYTHON) -m pylint trio_websocket/ tests/ autobahn/ examples/
Expand Down
29 changes: 27 additions & 2 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@
import trustme
from async_generator import async_generator, yield_
from trio.testing import memory_stream_pair
from wsproto.events import CloseConnection

try:
from trio.lowlevel import current_task
from trio.lowlevel import current_task # pylint: disable=ungrouped-imports
except ImportError:
from trio.hazmat import current_task
from trio.hazmat import current_task # pylint: disable=ungrouped-imports

from trio_websocket import (
connect_websocket,
Expand Down Expand Up @@ -925,6 +927,29 @@ async def handler(request):
await trio.sleep(.1)


@fail_after(DEFAULT_TEST_MAX_DURATION)
async def test_server_tcp_closed_on_close_connection_event(nursery):
"""ensure server closes TCP immediately after receiving CloseConnection"""
server_stream_closed = trio.Event()

async def _close_stream_stub():
assert not server_stream_closed.is_set()
server_stream_closed.set()

async def handle_connection(request):
ws = await request.accept()
ws._close_stream = _close_stream_stub
await trio.sleep_forever()

server = await nursery.start(
partial(serve_websocket, handle_connection, HOST, 0, ssl_context=None))
client = await connect_websocket(nursery, HOST, server.port,
RESOURCE, use_ssl=False)
# send a CloseConnection event to server but leave client connected
await client._send(CloseConnection(code=1000))
await server_stream_closed.wait()


async def test_finalization_dropped_exception(echo_server, autojump_clock):
# Confirm that open_websocket finalization does not contribute to dropped
# exceptions as described in https://github.com/python-trio/trio/issues/1559.
Expand Down
6 changes: 6 additions & 0 deletions trio_websocket/_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,12 @@ async def _handle_close_connection_event(self, event):
await self._send(event.response())
await self._close_web_socket(event.code, event.reason or None)
self._close_handshake.set()
# RFC: "When a server is instructed to Close the WebSocket Connection
# it SHOULD initiate a TCP Close immediately, and when a client is
# instructed to do the same, it SHOULD wait for a TCP Close from the
# server."
if self.is_server:
await self._close_stream()

async def _handle_message_event(self, event):
'''
Expand Down

0 comments on commit 719c06a

Please sign in to comment.